import React, { FormEventHandler, useCallback, useEffect, useState } from 'react'; import FocusTrap from 'focus-trap-react'; import { Box, Text, Input, Button, IconButton, Icon, Icons, Overlay, OverlayBackdrop, OverlayCenter, Header, config, color, Spinner, } from 'folds'; import { Method } from 'matrix-js-sdk'; import { AsyncStatus, useAsyncCallback } from '../../hooks/useAsyncCallback'; import { useMatrixClient } from '../../hooks/useMatrixClient'; import { stopPropagation } from '../../utils/keyboard'; import { useModalStyle } from '../../hooks/useModalStyle'; type ReportCategory = 'spam' | 'harassment' | 'inappropriate' | 'other'; const CATEGORY_LABELS: Record = { spam: 'Spam', harassment: 'Harassment', inappropriate: 'Inappropriate Content', other: 'Other', }; type ReportUserModalProps = { userId: string; onClose: () => void; }; export function ReportUserModal({ userId, onClose }: ReportUserModalProps) { const mx = useMatrixClient(); const modalStyle = useModalStyle(420); const [category, setCategory] = useState('spam'); const [reportState, submitReport] = useAsyncCallback( useCallback( async (reason: string) => { await mx.http.authedRequest( Method.Post, `/users/${encodeURIComponent(userId)}/report`, undefined, { reason }, ); }, [mx, userId], ), ); useEffect(() => { if (reportState.status === AsyncStatus.Success) { const timer = setTimeout(onClose, 1500); return () => clearTimeout(timer); } return undefined; }, [reportState.status, onClose]); const handleSubmit: FormEventHandler = (evt) => { evt.preventDefault(); if (reportState.status === AsyncStatus.Loading || reportState.status === AsyncStatus.Success) { return; } const target = evt.target as HTMLFormElement; const reasonInput = target.elements.namedItem('reasonInput') as HTMLInputElement | null; const reasonText = reasonInput?.value.trim() ?? ''; const fullReason = `[${CATEGORY_LABELS[category]}] ${reasonText}`; submitReport(fullReason); }; const reportError = reportState.status === AsyncStatus.Error ? (reportState.error as { errcode?: string; httpStatus?: number }) : undefined; const errcode = reportError?.errcode; const errorMsg = errcode === 'M_LIMIT_EXCEEDED' ? 'You are being rate limited. Please wait before reporting again.' : errcode === 'M_FORBIDDEN' ? 'You cannot report this user.' : errcode === 'M_UNRECOGNIZED' || reportError?.httpStatus === 404 ? 'User reporting is not supported by your homeserver.' : 'Failed to submit report. Please try again.'; return ( }>
Report User
Report this user to your homeserver admins. Please describe the issue below. Category ) => setCategory(e.target.value as ReportCategory) } style={{ padding: `${config.space.S200} ${config.space.S300}`, borderRadius: config.radii.R300, border: `1px solid ${color.Surface.ContainerLine}`, background: color.Surface.Container, color: color.Surface.OnContainer, fontSize: 'inherit', fontFamily: 'inherit', width: '100%', }} > {(Object.keys(CATEGORY_LABELS) as ReportCategory[]).map((key) => ( ))} Reason {reportState.status === AsyncStatus.Error && ( {errorMsg} )} {reportState.status === AsyncStatus.Success && ( User has been reported to the server. )}
); }