import { FlowRouter } from 'meteor/kadira:flow-router'; import React, { memo, useCallback, useEffect, useMemo, useState } from 'react'; import { useMutableCallback, useDebouncedCallback } from '@rocket.chat/fuselage-hooks'; import { Box, Modal, ButtonGroup, Button, TextInput, Icon, Field, ToggleSwitch } from '@rocket.chat/fuselage'; import { useTranslation } from '../../contexts/TranslationContext'; import { useForm } from '../../hooks/useForm'; import { useEndpointActionExperimental } from '../../hooks/useEndpointAction'; import UserAutoCompleteMultiple from '../../../ee/client/audit/UserAutoCompleteMultiple'; import { useSetting } from '../../contexts/SettingsContext'; import { usePermission } from '../../contexts/AuthorizationContext'; import { useMethod } from '../../contexts/ServerContext'; export const CreateChannel = ({ values, handlers, hasUnsavedChanges, onChangeUsers, onChangeType, onChangeBroadcast, canOnlyCreateOneType, e2eEnabledForPrivateByDefault, onCreate, onClose, }) => { const t = useTranslation(); const e2eEnabled = useSetting('E2E_Enable'); const namesValidation = useSetting('UTF8_Names_Validation'); const allowSpecialNames = useSetting('UI_Allow_room_names_with_special_chars'); const channelNameExists = useMethod('roomNameExists'); const channelNameRegex = useMemo(() => { if (allowSpecialNames) { return ''; } const regex = new RegExp(`^${ namesValidation }$`); return regex; }, [allowSpecialNames, namesValidation]); const [nameError, setNameError] = useState(); const checkName = useDebouncedCallback(async (name) => { setNameError(false); if (hasUnsavedChanges) { return; } if (!name || name.length === 0) { return setNameError(t('Field_required')); } if (!channelNameRegex.test(name)) { return setNameError(t('error-invalid-name')); } const isNotAvailable = await channelNameExists(name); if (isNotAvailable) { return setNameError(t('Channel_already_exist', name)); } }, 100, [name]); useEffect(() => { checkName(values.name); }, [checkName, values.name]); const e2edisabled = useMemo(() => !values.type || values.broadcast || !e2eEnabled || e2eEnabledForPrivateByDefault, [e2eEnabled, e2eEnabledForPrivateByDefault, values.broadcast, values.type]); const canSave = useMemo(() => hasUnsavedChanges && !nameError, [hasUnsavedChanges, nameError]); return {t('Create_channel')} {t('Name')} } placeholder={t('Channel_name')} onChange={handlers.handleName}/> {hasUnsavedChanges && nameError && {nameError} } {t('Topic')} ({t('optional')}) {t('Private')} {values.type ? t('Only_invited_users_can_acess_this_channel') : t('Everyone_can_access_this_channel')} {t('Read_only')} {t('All_users_in_the_channel_can_write_new_messages')} {t('Encrypted')} {values.type ? t('Encrypted_channel_Description') : t('Encrypted_not_available')} {t('Broadcast')} {t('Broadcast_channel_Description')} {`${ t('Add_members') } (${ t('optional') })`} ; }; export default memo(({ onClose, }) => { const createChannel = useEndpointActionExperimental('POST', 'channels.create'); const createPrivateChannel = useEndpointActionExperimental('POST', 'groups.create'); const setChannelDescription = useEndpointActionExperimental('POST', 'channels.setDescription'); const setPrivateChannelDescription = useEndpointActionExperimental('POST', 'groups.setDescription'); const canCreateChannel = usePermission('create-c'); const canCreatePrivateChannel = usePermission('create-p'); const e2eEnabledForPrivateByDefault = useSetting('E2E_Enabled_Default_PrivateRooms'); const canOnlyCreateOneType = useMemo(() => { if (!canCreateChannel && canCreatePrivateChannel) { return 'p'; } if (canCreateChannel && !canCreatePrivateChannel) { return 'c'; } return false; }, [canCreateChannel, canCreatePrivateChannel]); const initialValues = { users: [], name: '', description: '', type: canOnlyCreateOneType ? canOnlyCreateOneType === 'p' : true, readOnly: false, encrypted: e2eEnabledForPrivateByDefault, broadcast: false, }; const { values, handlers, hasUnsavedChanges } = useForm(initialValues); const { users, name, description, type, readOnly, broadcast, encrypted, } = values; const { handleUsers, handleEncrypted, handleType, handleBroadcast, handleReadOnly, } = handlers; const onChangeUsers = useMutableCallback((value, action) => { if (!action) { if (users.includes(value)) { return; } return handleUsers([...users, value]); } handleUsers(users.filter((current) => current !== value)); }); const onChangeType = useMutableCallback((value) => { if (value) { handleEncrypted(false); } return handleType(value); }); const onChangeBroadcast = useMutableCallback((value) => { if (value) { handleEncrypted(false); handleReadOnly(true); } handleReadOnly(value); return handleBroadcast(value); }); const onCreate = useCallback(async () => { const goToRoom = (rid) => { FlowRouter.goToRoomById(rid); }; const params = { name, members: users, readOnly, extraData: { broadcast, encrypted, }, }; let roomData; if (type) { roomData = await createPrivateChannel(params); goToRoom(roomData.group._id); } else { roomData = await createChannel(params); goToRoom(roomData.channel._id); } if (roomData.success && roomData.group && description) { setPrivateChannelDescription({ description, roomName: roomData.group.name }); } else if (roomData.success && roomData.channel && description) { setChannelDescription({ description, roomName: roomData.channel.name }); } onClose(); }, [broadcast, createChannel, createPrivateChannel, description, encrypted, name, onClose, readOnly, setChannelDescription, setPrivateChannelDescription, type, users, ]); return ; });