import React, { ChangeEventHandler, FormEventHandler, KeyboardEventHandler, useCallback, useMemo, useRef, useState, } from 'react'; import { Overlay, OverlayBackdrop, OverlayCenter, Box, Header, config, Text, IconButton, Icon, Icons, Input, Button, Spinner, color, TextArea, Dialog, Menu, toRem, Scroll, MenuItem, } from 'folds'; import { Room } from 'matrix-js-sdk'; import { isKeyHotkey } from 'is-hotkey'; import FocusTrap from 'focus-trap-react'; import { stopPropagation } from '../../utils/keyboard'; import { useDirectUsers } from '../../hooks/useDirectUsers'; import { getMxIdLocalPart, getMxIdServer, isUserId } from '../../utils/matrix'; import { Membership } from '../../../types/matrix/room'; import { useAsyncSearch, UseAsyncSearchOptions } from '../../hooks/useAsyncSearch'; import { highlightText, makeHighlightRegex } from '../../plugins/react-custom-html-parser'; import { AsyncStatus, useAsyncCallback } from '../../hooks/useAsyncCallback'; import { useMatrixClient } from '../../hooks/useMatrixClient'; import { BreakWord } from '../../styles/Text.css'; import { useAlive } from '../../hooks/useAlive'; const SEARCH_OPTIONS: UseAsyncSearchOptions = { limit: 1000, matchOptions: { contain: true, }, }; const getUserIdString = (userId: string) => getMxIdLocalPart(userId) ?? userId; type InviteUserProps = { room: Room; requestClose: () => void; }; export function InviteUserPrompt({ room, requestClose }: InviteUserProps) { const mx = useMatrixClient(); const alive = useAlive(); const inputRef = useRef(null); const directUsers = useDirectUsers(); const [validUserId, setValidUserId] = useState(); const filteredUsers = useMemo( () => directUsers.filter((userId) => { const membership = room.getMember(userId)?.membership; return membership !== Membership.Join; }), [directUsers, room] ); const [result, search, resetSearch] = useAsyncSearch( filteredUsers, getUserIdString, SEARCH_OPTIONS ); const queryHighlighRegex = result?.query ? makeHighlightRegex(result.query.split(' ')) : undefined; const [inviteState, invite] = useAsyncCallback( useCallback( async (userId, reason) => { await mx.invite(room.roomId, userId, reason); }, [mx, room] ) ); const inviting = inviteState.status === AsyncStatus.Loading; const handleReset = () => { if (inputRef.current) inputRef.current.value = ''; setValidUserId(undefined); resetSearch(); }; const handleSubmit: FormEventHandler = (evt) => { evt.preventDefault(); const target = evt.target as HTMLFormElement | undefined; if (inviting || !validUserId) return; const reasonInput = target?.reasonInput as HTMLTextAreaElement | undefined; const reason = reasonInput?.value.trim(); invite(validUserId, reason || undefined).then(() => { if (alive()) { handleReset(); if (reasonInput) reasonInput.value = ''; } }); }; const handleSearchChange: ChangeEventHandler = (evt) => { const value = evt.currentTarget.value.trim(); if (isUserId(value)) { setValidUserId(value); } else { setValidUserId(undefined); const term = getMxIdLocalPart(value) ?? (value.startsWith('@') ? value.slice(1) : value); if (term) { search(term); } else { resetSearch(); } } }; const handleUserId = (userId: string) => { if (inputRef.current) { inputRef.current.value = userId; setValidUserId(userId); resetSearch(); inputRef.current.focus(); } }; const handleKeyDown: KeyboardEventHandler = (evt) => { if (isKeyHotkey('escape', evt)) { resetSearch(); return; } if (isKeyHotkey('tab', evt) && result && result.items.length > 0) { evt.preventDefault(); const userId = result.items[0]; handleUserId(userId); } }; return ( }> inputRef.current, clickOutsideDeactivates: true, onDeactivate: requestClose, escapeDeactivates: stopPropagation, }} >
Invite
User ID
{result && result.items.length > 0 && ( isKeyHotkey('arrowdown', evt), isKeyBackward: (evt: KeyboardEvent) => isKeyHotkey('arrowup', evt), escapeDeactivates: stopPropagation, }} >
{result.items.map((userId) => { const username = `${getMxIdLocalPart(userId)}`; const userServer = getMxIdServer(userId); return ( handleUserId(userId)} after={ {userServer} } disabled={inviting} > {queryHighlighRegex ? highlightText(queryHighlighRegex, [ username ?? userId, ]) : username} ); })}
)}
Reason (Optional)