import React, { FormEventHandler, useCallback, useState } from 'react'; import { MatrixError, Room } from 'matrix-js-sdk'; import { Box, Button, Chip, color, config, Icon, Icons, Input, Spinner, Switch, Text, TextArea, } from 'folds'; import { SettingTile } from '../../components/setting-tile'; import { SequenceCard } from '../../components/sequence-card'; import { knockRestrictedSupported, knockSupported, restrictedSupported } from '../../utils/matrix'; import { useMatrixClient } from '../../hooks/useMatrixClient'; import { millisecondsToMinutes, replaceSpaceWithDash } from '../../utils/common'; import { AsyncStatus, useAsyncCallback } from '../../hooks/useAsyncCallback'; import { useCapabilities } from '../../hooks/useCapabilities'; import { useAlive } from '../../hooks/useAlive'; import { ErrorCode } from '../../cs-errorcode'; import { createRoom, CreateRoomAliasInput, CreateRoomData, CreateRoomKind, CreateRoomKindSelector, RoomVersionSelector, } from '../../components/create-room'; import { RoomType } from '../../../types/matrix/room'; const getCreateSpaceKindToIcon = (kind: CreateRoomKind) => { if (kind === CreateRoomKind.Private) return Icons.SpaceLock; if (kind === CreateRoomKind.Restricted) return Icons.Space; return Icons.SpaceGlobe; }; type CreateSpaceFormProps = { defaultKind?: CreateRoomKind; space?: Room; onCreate?: (roomId: string) => void; }; export function CreateSpaceForm({ defaultKind, space, onCreate }: CreateSpaceFormProps) { const mx = useMatrixClient(); const alive = useAlive(); const capabilities = useCapabilities(); const roomVersions = capabilities['m.room_versions']; const [selectedRoomVersion, selectRoomVersion] = useState(roomVersions?.default ?? '1'); const allowRestricted = space && restrictedSupported(selectedRoomVersion); const [kind, setKind] = useState( defaultKind ?? allowRestricted ? CreateRoomKind.Restricted : CreateRoomKind.Private ); const [federation, setFederation] = useState(true); const [knock, setKnock] = useState(false); const [advance, setAdvance] = useState(false); const allowKnock = kind === CreateRoomKind.Private && knockSupported(selectedRoomVersion); const allowKnockRestricted = kind === CreateRoomKind.Restricted && knockRestrictedSupported(selectedRoomVersion); const handleRoomVersionChange = (version: string) => { if (!restrictedSupported(version)) { setKind(CreateRoomKind.Private); } selectRoomVersion(version); }; const [createState, create] = useAsyncCallback( useCallback((data) => createRoom(mx, data), [mx]) ); const loading = createState.status === AsyncStatus.Loading; const error = createState.status === AsyncStatus.Error ? createState.error : undefined; const disabled = createState.status === AsyncStatus.Loading; const handleSubmit: FormEventHandler = (evt) => { evt.preventDefault(); if (disabled) return; const form = evt.currentTarget; const nameInput = form.nameInput as HTMLInputElement | undefined; const topicTextArea = form.topicTextAria as HTMLTextAreaElement | undefined; const aliasInput = form.aliasInput as HTMLInputElement | undefined; const roomName = nameInput?.value.trim(); const roomTopic = topicTextArea?.value.trim(); const aliasLocalPart = aliasInput && aliasInput.value ? replaceSpaceWithDash(aliasInput.value) : undefined; if (!roomName) return; const publicRoom = kind === CreateRoomKind.Public; let roomKnock = false; if (allowKnock && kind === CreateRoomKind.Private) { roomKnock = knock; } if (allowKnockRestricted && kind === CreateRoomKind.Restricted) { roomKnock = knock; } create({ version: selectedRoomVersion, type: RoomType.Space, parent: space, kind, name: roomName, topic: roomTopic || undefined, aliasLocalPart: publicRoom ? aliasLocalPart : undefined, knock: roomKnock, allowFederation: federation, }).then((roomId) => { if (alive()) { onCreate?.(roomId); } }); }; return ( Access Name } name="nameInput" autoFocus size="500" variant="SurfaceVariant" radii="400" autoComplete="off" disabled={disabled} /> Topic (Optional)