import React, { useMemo } from 'react'; import { Box, Icon, IconButton, Icons, Text, as } from 'folds'; import { Room } from 'matrix-js-sdk'; import classNames from 'classnames'; import { useSetAtom } from 'jotai'; import { roomIdToTypingMembersAtom } from '../../state/typingMembers'; import { TypingIndicator } from '../../components/typing-indicator'; import { getMemberDisplayName } from '../../utils/room'; import { getMxIdLocalPart } from '../../utils/matrix'; import * as css from './RoomViewTyping.css'; import { useMatrixClient } from '../../hooks/useMatrixClient'; import { useRoomTypingMember } from '../../hooks/useRoomTypingMembers'; export type RoomViewTypingProps = { room: Room; }; export const RoomViewTyping = as<'div', RoomViewTypingProps>( ({ className, room, ...props }, ref) => { const setTypingMembers = useSetAtom(roomIdToTypingMembersAtom); const mx = useMatrixClient(); const typingMembers = useRoomTypingMember(room.roomId); const myUserId = mx.getUserId(); const typingNames = useMemo( () => typingMembers .filter((receipt) => receipt.userId !== myUserId) .map( (receipt) => getMemberDisplayName(room, receipt.userId) ?? getMxIdLocalPart(receipt.userId), ) .reverse(), [typingMembers, myUserId, room], ); // A single, non-truncated string for assistive technology to announce. // Computed even when empty so the live region can stay mounted (below) — // a `role="status"` region added to the DOM together with its first text // is not reliably announced by some screen readers. let typingAnnouncement = ''; if (typingNames.length === 1) { typingAnnouncement = `${typingNames[0]} is typing`; } else if (typingNames.length === 2) { typingAnnouncement = `${typingNames[0]} and ${typingNames[1]} are typing`; } else if (typingNames.length === 3) { typingAnnouncement = `${typingNames[0]}, ${typingNames[1]} and ${typingNames[2]} are typing`; } else { typingAnnouncement = `${typingNames[0]}, ${typingNames[1]}, ${typingNames[2]} and ${ typingNames.length - 3 } others are typing`; } const handleDropAll = () => { // some homeserver does not timeout typing status // we have given option so user can drop their typing status typingMembers.forEach((receipt) => setTypingMembers({ type: 'DELETE', roomId: room.roomId, userId: receipt.userId, }), ); }; return (