diff --git a/packages/examples/sdk-frontend-react/src/app/ChatUITest/ChatViewComponent.tsx b/packages/examples/sdk-frontend-react/src/app/ChatUITest/ChatViewComponent.tsx index 6e82062fa..254dbc022 100644 --- a/packages/examples/sdk-frontend-react/src/app/ChatUITest/ChatViewComponent.tsx +++ b/packages/examples/sdk-frontend-react/src/app/ChatUITest/ChatViewComponent.tsx @@ -15,11 +15,12 @@ const ChatViewComponentTest = () => {

Chat UI Test page

{/* {console.log('in close')}} /> */} - {/* {console.log('in close')}} modalBackground={MODAL_BACKGROUND_TYPE.OVERLAY} modalPositionType={MODAL_POSITION_TYPE.RELATIVE}/> */} + {console.log('in close')}} modalBackground={MODAL_BACKGROUND_TYPE.OVERLAY} modalPositionType={MODAL_POSITION_TYPE.RELATIVE}/> console.log("BOIIII RETURNNNSSSSS")} - chatId='0x99A08ac6254dcf7ccc37CeC662aeba8eFA666666' + chatId='92ed5f3f3bcdf58976ce11395786398f6f9e3048d76dc7e6f53ea5d77092fdd6' + limit={10} isConnected={true} groupInfoModalBackground={MODAL_BACKGROUND_TYPE.OVERLAY} diff --git a/packages/uiweb/src/lib/components/chat/ChatProfile/AddWalletContent.tsx b/packages/uiweb/src/lib/components/chat/ChatProfile/AddWalletContent.tsx index e99062b39..536548606 100644 --- a/packages/uiweb/src/lib/components/chat/ChatProfile/AddWalletContent.tsx +++ b/packages/uiweb/src/lib/components/chat/ChatProfile/AddWalletContent.tsx @@ -35,6 +35,8 @@ type AddWalletContentProps = { groupMembers: any; isLoading?: boolean; modalHeader: string; + title?: string; + submitButtonTitle?: string; }; export const AddWalletContent = ({ onSubmit, @@ -44,6 +46,8 @@ export const AddWalletContent = ({ handleMemberList, groupMembers, isLoading, + title, + submitButtonTitle, }: AddWalletContentProps) => { const theme = useContext(ThemeContext); @@ -86,6 +90,10 @@ export const AddWalletContent = ({ const addMemberToList = (member: User) => { let errorMessage = ''; + const isMemberAlreadyAdded = memberList?.find( + (user: any) => user.wallets.toLowerCase() === member.wallets.toLowerCase() + ); + console.log('member', member); errorMessage = addWalletValidation( member, @@ -101,7 +109,7 @@ export const AddWalletContent = ({ toastType: 'ERROR', getToastIcon: (size) => , }); - } else { + } else if(!isMemberAlreadyAdded) { handleMemberList((prev: any) => [...prev, { ...member, isAdmin: false }]); } @@ -123,7 +131,7 @@ export const AddWalletContent = ({ flexDirection="column" padding={isMobile ? '0px auto' : '0px 10px'} > - +
{groupMembers - ? `0${memberList?.length + groupMembers?.length} / 09 Members` - : `0${memberList?.length} / 09 Members`} + ? `0${memberList?.length + groupMembers?.length} / 5000 Members` + : `0${memberList?.length} / 5000 Members`}
@@ -162,7 +170,7 @@ export const AddWalletContent = ({ ) } - {memberList?.map((member: any, index: any) => ( + {memberList && memberList?.map((member: any, index: any) => ( onSubmit()} + onClick={() => { + // console.log(groupMembers); + onSubmit() + }} isLoading={isLoading} memberListCount={memberList?.length > 0} theme={theme} > - {!isLoading && groupMembers ? 'Add To Group' : ''} + {!isLoading && groupMembers ? (submitButtonTitle ? submitButtonTitle : 'Add To Group'): ''} {isLoading && } diff --git a/packages/uiweb/src/lib/components/chat/CreateGroup/AddWallets.tsx b/packages/uiweb/src/lib/components/chat/CreateGroup/AddWallets.tsx new file mode 100644 index 000000000..db2a4f965 --- /dev/null +++ b/packages/uiweb/src/lib/components/chat/CreateGroup/AddWallets.tsx @@ -0,0 +1,95 @@ +import React from "react"; +import { Section, Span } from "../../reusables"; +import { ModalHeader } from "../reusables"; +import { AddWalletContent } from "../ChatProfile/AddWalletContent"; +import { GrouInfoType as GroupInfoType } from "../../chat/types/index" +import { ProfilePicture } from "../../../config"; +import { MdCheckCircle, MdError } from "react-icons/md"; +import { useCreateGatedGroup } from "../../../hooks/chat/useCreateGatedGroup"; +import useToast from "../reusables/NewToast"; +import { GroupInputDetailsType } from "./CreateGroupModal"; + +interface AddWalletsInCreateGroupProps { + groupInputDetails: GroupInputDetailsType; + setGroupInputDetails: React.Dispatch>; + groupMembers: string[]; + setGroupMembers: React.Dispatch>; + groupAdmins: string[]; + criteriaStateManager: any; + checked: boolean; + groupEncryptionType: string; + onClose: () => void; + handlePrevious: () => void; +} + +const AddWalletsInCreateGroup = ({ handlePrevious, onClose,groupInputDetails, groupEncryptionType, checked, criteriaStateManager, groupMembers, setGroupMembers }: AddWalletsInCreateGroupProps) => { + const { createGatedGroup } = useCreateGatedGroup(); + const groupInfoToast = useToast(); + const getEncryptionType = () => { + if (groupEncryptionType === 'encrypted') { + return false; + } + return true; + }; + + const showError = (errorMessage: string) => { + groupInfoToast.showMessageToast({ + toastTitle: 'Error', + toastMessage: errorMessage, + toastType: 'ERROR', + getToastIcon: (size) => , + }); + }; + + const createGroupService = async () => { + const groupInfo: GroupInfoType = { + groupName: groupInputDetails.groupName, + groupDescription: groupInputDetails.groupDescription, + groupImage: groupInputDetails.groupImage || ProfilePicture, + isPublic: getEncryptionType(), + members: groupInputDetails.groupMembers.filter((member: any) => !member.isAdmin).map((member: any) => member.wallets), + admins: groupInputDetails.groupMembers.filter((member: any) => member.isAdmin).map((member: any) => member.wallets), + }; + const rules: any = checked ? criteriaStateManager.generateRule() : {}; + const isSuccess = await createGatedGroup(groupInfo, rules); + if (isSuccess === true) { + groupInfoToast.showMessageToast({ + toastTitle: 'Success', + toastMessage: 'Group created successfully', + toastType: 'SUCCESS', + getToastIcon: (size: string | number | undefined) => , + }); + onClose(); + } else { + showError('Group creation failed'); + } + } + + const verifyAndCreateGroup = async () => { + if (groupEncryptionType.trim() === '') { + showError('Group encryption type is not selected'); + return; + } + + await createGroupService(); + }; + + return ( +
+ +
+ ) +} + +export default AddWalletsInCreateGroup; \ No newline at end of file diff --git a/packages/uiweb/src/lib/components/chat/CreateGroup/CreateGroupModal.tsx b/packages/uiweb/src/lib/components/chat/CreateGroup/CreateGroupModal.tsx index 5c7252688..4054f61fd 100644 --- a/packages/uiweb/src/lib/components/chat/CreateGroup/CreateGroupModal.tsx +++ b/packages/uiweb/src/lib/components/chat/CreateGroup/CreateGroupModal.tsx @@ -11,7 +11,7 @@ import { TextInput } from '../reusables/TextInput'; import { TextArea } from '../reusables/TextArea'; import { Section, Span } from '../../reusables'; import { Button } from '../reusables'; -import { CreateGroupType } from './CreateGroupType'; +import { CreateGroupType, GROUP_TYPE_OPTIONS } from './CreateGroupType'; import useToast from '../reusables/NewToast'; import { CreateGroupModalProps, IChatTheme, MODAL_BACKGROUND_TYPE, MODAL_POSITION_TYPE } from '../exportedTypes'; import useMediaQuery from '../../../hooks/useMediaQuery'; @@ -28,21 +28,25 @@ import { Image } from '../../../config/styles'; import { ProfilePicture, device } from '../../../config'; import { CriteriaValidationErrorType } from '../types'; import AutoImageClipper from './AutoImageClipper'; +import AddWalletsInCreateGroup from './AddWallets'; export const CREATE_GROUP_STEP_KEYS = { INPUT_DETAILS: 1, GROUP_TYPE: 2, DEFINITE_CONDITION: 3, ADD_CRITERIA: 4, + ADD_MEMBERS: 5, } as const; export type CreateGroupStepKeys = typeof CREATE_GROUP_STEP_KEYS[keyof typeof CREATE_GROUP_STEP_KEYS]; -interface GroupInputDetailsType { +export interface GroupInputDetailsType { groupName: string; groupDescription: string; groupImage: string; + groupMembers: string[]; + groupAdmins: string[]; } export const CreateGroupModal: React.FC = ({ @@ -58,6 +62,12 @@ export const CreateGroupModal: React.FC = ({ const handleNext = () => { setActiveComponent((activeComponent + 1) as CreateGroupStepKeys); }; + const handleAddWallets = () => { + setActiveComponent((activeComponent + 3) as CreateGroupStepKeys) + } + const handlePreviousfromAddWallets = () => { + setActiveComponent((activeComponent - 3) as CreateGroupStepKeys) + } const handlePrevious = () => { setActiveComponent((activeComponent - 1) as CreateGroupStepKeys); }; @@ -74,6 +84,12 @@ export const CreateGroupModal: React.FC = ({ }, [activeComponent]); const useDummyGroupInfo = false; + const [groupMembers, setGroupMembers] = useState([]); + const [groupAdmins, setGroupAdmins] = useState([]); + const [checked, setChecked] = useState(true); + const [groupEncryptionType, setGroupEncryptionType] = useState( + GROUP_TYPE_OPTIONS[0].value + ); const [groupInputDetails, setGroupInputDetails] = useState({ groupName: useDummyGroupInfo ? 'This is duumy group name' : '', @@ -81,28 +97,47 @@ export const CreateGroupModal: React.FC = ({ ? 'This is dummy group description for testing' : '', groupImage: useDummyGroupInfo ? ProfilePicture : '', + groupMembers: useDummyGroupInfo ? groupMembers : [], + groupAdmins: useDummyGroupInfo ? groupAdmins : [], }); + const [isImageUploaded, setIsImageUploaded] = useState(false); + + useEffect(() => { + setGroupInputDetails({ + ...groupInputDetails, + groupMembers: groupMembers, + }); + }, [groupMembers]) const renderComponent = () => { switch (activeComponent) { case CREATE_GROUP_STEP_KEYS.INPUT_DETAILS: return ( ); case CREATE_GROUP_STEP_KEYS.GROUP_TYPE: return ( ); case CREATE_GROUP_STEP_KEYS.DEFINITE_CONDITION: @@ -122,6 +157,10 @@ export const CreateGroupModal: React.FC = ({ onClose={onClose} /> ); + case CREATE_GROUP_STEP_KEYS.ADD_MEMBERS: + return ( + + ) default: return ( = ({ onClose={onClose} groupInputDetails={groupInputDetails} setGroupInputDetails={setGroupInputDetails} + isImageUploaded={isImageUploaded} + setIsImageUploaded={setIsImageUploaded} /> ); } @@ -147,6 +188,13 @@ export interface ModalHeaderProps { handlePrevious?: () => void; onClose: () => void; criteriaStateManager: CriteriaStateManagerType; + checked?: boolean; + setChecked?: React.Dispatch>; + groupEncryptionType?: string; + setGroupEncryptionType?: React.Dispatch>; + handleAddWallets?: () => void; + isImageUploaded?: boolean; + setIsImageUploaded?: React.Dispatch>; } interface GroupDetailState { @@ -165,15 +213,15 @@ const CreateGroupDetail = ({ onClose, groupInputDetails, setGroupInputDetails, + isImageUploaded, + setIsImageUploaded, }: ModalHeaderProps & GroupDetailState) => { - const groupInfoToast = useToast(); const { groupName, groupDescription, groupImage } = groupInputDetails; const theme = useContext(ThemeContext); const [validationErrors, setValidationErrors] = useState({}); const fileUploadInputRef = useRef(null); const isMobile = useMediaQuery(device.mobileL); - const [isImageUploaded, setIsImageUploaded] = useState(false); const [imageSrc, setImageSrc] = useState(); const handleChange = (e: Event) => { @@ -185,13 +233,16 @@ const CreateGroupDetail = ({ } if ( (e.target as HTMLInputElement).files && - ((e.target as HTMLInputElement).files as FileList).length + ((e.target as HTMLInputElement).files as FileList).length && + setIsImageUploaded ) { setIsImageUploaded(true); setGroupInputDetails({ groupDescription, groupName, groupImage: '', + groupMembers: [], + groupAdmins: [], }); const reader = new FileReader(); reader.readAsDataURL(e.target.files[0]); @@ -207,15 +258,6 @@ const CreateGroupDetail = ({ } }; - const showError = (errorMessage: string) => { - groupInfoToast.showMessageToast({ - toastTitle: 'Error', - toastMessage: errorMessage, - toastType: 'ERROR', - getToastIcon: (size) => , - }); - }; - const verifyAndHandelNext = () => { const skipVerify = false; @@ -247,7 +289,6 @@ const CreateGroupDetail = ({ fileUploadInputRef.current.click(); } }; - //groupImage and desccription is optional return (
= [ +export const GROUP_TYPE_OPTIONS: Array = [ { heading: 'Public', subHeading: 'Anyone can view chats, even without joining', @@ -132,67 +127,18 @@ const AddConditionSection = ({ export const CreateGroupType = ({ onClose, handlePrevious, - groupInputDetails, handleNext, criteriaStateManager, + checked = false, + setChecked, + handleAddWallets, }: ModalHeaderProps & GroupTypeState) => { - const [checked, setChecked] = useState(true); const [groupEncryptionType, setGroupEncryptionType] = useState( GROUP_TYPE_OPTIONS[0].value ); - const { createGatedGroup, loading } = useCreateGatedGroup(); - const groupInfoToast = useToast(); const theme = useContext(ThemeContext); - - const getEncryptionType = () => { - if (groupEncryptionType === 'encrypted') { - return false; - } - return true; - }; - - const createGroupService = async () => { - const groupInfo: GroupInfoType = { - groupName: groupInputDetails.groupName, - groupDescription: groupInputDetails.groupDescription, - groupImage: groupInputDetails.groupImage || ProfilePicture, - isPublic: getEncryptionType(), - }; - const rules: any = checked ? criteriaStateManager.generateRule() : {}; - const isSuccess = await createGatedGroup(groupInfo, rules); - if (isSuccess === true) { - groupInfoToast.showMessageToast({ - toastTitle: 'Success', - toastMessage: 'Group created successfully', - toastType: 'SUCCESS', - getToastIcon: (size) => , - }); - } else { - showError('Group creation failed'); - } - - onClose(); - }; - - const verifyAndCreateGroup = async () => { - if (groupEncryptionType.trim() === '') { - showError('Group encryption type is not selected'); - return; - } - - await createGroupService(); - }; - - const showError = (errorMessage: string) => { - groupInfoToast.showMessageToast({ - toastTitle: 'Error', - toastMessage: errorMessage, - toastType: 'ERROR', - getToastIcon: (size) => , - }); - }; - + return (
setChecked(!checked)} + onToggle={() => setChecked ? setChecked(!checked) : null} /> {checked && ( @@ -254,9 +200,8 @@ export const CreateGroupType = ({
-
diff --git a/packages/uiweb/src/lib/components/chat/types/index.ts b/packages/uiweb/src/lib/components/chat/types/index.ts index 0f51020e9..2b696a180 100644 --- a/packages/uiweb/src/lib/components/chat/types/index.ts +++ b/packages/uiweb/src/lib/components/chat/types/index.ts @@ -5,6 +5,8 @@ export interface GrouInfoType{ groupDescription:string; groupImage:string; isPublic: boolean; + members: string[]; + admins: string[]; } export const TYPE = { diff --git a/packages/uiweb/src/lib/hooks/chat/useCreateGatedGroup.ts b/packages/uiweb/src/lib/hooks/chat/useCreateGatedGroup.ts index 2753671d6..b575dd58a 100644 --- a/packages/uiweb/src/lib/hooks/chat/useCreateGatedGroup.ts +++ b/packages/uiweb/src/lib/hooks/chat/useCreateGatedGroup.ts @@ -17,8 +17,8 @@ export const useCreateGatedGroup = () => { groupDescription:groupInfoType.groupDescription, groupImage:groupInfoType.groupImage, isPublic: groupInfoType.isPublic, - members: [], - admins: [], + members: groupInfoType.members, + admins: groupInfoType.admins, account: account || undefined, env: env, pgpPrivateKey: pgpPrivateKey || undefined, diff --git a/packages/uiweb/src/lib/types/index.ts b/packages/uiweb/src/lib/types/index.ts index f345c9f2b..9375255bf 100644 --- a/packages/uiweb/src/lib/types/index.ts +++ b/packages/uiweb/src/lib/types/index.ts @@ -24,7 +24,7 @@ export interface IMessageIPFS { link: string | null; timestamp?: number; encType: string; - encryptedSecret: string; + encryptedSecret: string | null; icon?: ReactElement; }