import { useEffect, useState } from 'react'; import { MatrixEvent, Room, RoomEvent, RoomEventHandlerMap, EventStatus } from 'matrix-js-sdk'; import { useMatrixClient } from './useMatrixClient'; export enum MessageDeliveryStatus { Sending = 'sending', Sent = 'sent', Read = 'read', } function getDeliveryStatus( room: Room, mEvent: MatrixEvent, myUserId: string ): MessageDeliveryStatus | null { if (mEvent.getSender() !== myUserId) return null; const { status } = mEvent; if ( status === EventStatus.SENDING || status === EventStatus.ENCRYPTING || status === EventStatus.QUEUED ) { return MessageDeliveryStatus.Sending; } if (status === EventStatus.NOT_SENT || status === EventStatus.CANCELLED) return null; const eventId = mEvent.getId(); if (!eventId || !eventId.startsWith('$')) return MessageDeliveryStatus.Sending; const members = room.getMembers(); const otherMembers = members.filter((m) => m.userId !== myUserId && m.membership !== 'invite'); const hasReader = otherMembers.some((member) => room.hasUserReadEvent(member.userId, eventId)); if (hasReader) return MessageDeliveryStatus.Read; return MessageDeliveryStatus.Sent; } export function useMessageStatus(room: Room, mEvent: MatrixEvent): MessageDeliveryStatus | null { const mx = useMatrixClient(); const myUserId = mx.getSafeUserId(); const isOwnMessage = mEvent.getSender() === myUserId; const [status, setStatus] = useState(() => getDeliveryStatus(room, mEvent, myUserId) ); useEffect(() => { if (!isOwnMessage) return undefined; setStatus(getDeliveryStatus(room, mEvent, myUserId)); const handleReceipt: RoomEventHandlerMap[RoomEvent.Receipt] = (_event, r) => { if (r.roomId !== room.roomId) return; setStatus(getDeliveryStatus(room, mEvent, myUserId)); }; const handleLocalEcho: RoomEventHandlerMap[RoomEvent.LocalEchoUpdated] = (event, r) => { if (r.roomId !== room.roomId) return; if (event.getId() !== mEvent.getId()) return; setStatus(getDeliveryStatus(room, mEvent, myUserId)); }; room.on(RoomEvent.Receipt, handleReceipt); room.on(RoomEvent.LocalEchoUpdated, handleLocalEcho); return () => { room.removeListener(RoomEvent.Receipt, handleReceipt); room.removeListener(RoomEvent.LocalEchoUpdated, handleLocalEcho); }; }, [room, mEvent, myUserId, isOwnMessage]); return status; }