75 lines
2.4 KiB
TypeScript
75 lines
2.4 KiB
TypeScript
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<MessageDeliveryStatus | null>(() =>
|
|
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;
|
|
}
|