59 lines
2 KiB
TypeScript
59 lines
2 KiB
TypeScript
import { MatrixClient } from 'matrix-js-sdk';
|
|
import { useMemo, useRef } from 'react';
|
|
import { TYPING_TIMEOUT_MS } from '../state/typingMembers';
|
|
|
|
type TypingStatusUpdater = (typing: boolean) => void;
|
|
|
|
// `disabled` is the caller's opt-out for surfaces where typing
|
|
// notifications would leak to the wrong audience. The Matrix
|
|
// `m.typing` EDU is strictly room-scoped (the spec has no `thread_id`
|
|
// field), so a thread composer that called `mx.sendTyping(roomId, ...)`
|
|
// would broadcast «X is typing» to every member watching the main
|
|
// channel chat — even though the user is privately drafting in a
|
|
// thread drawer. The drawer passes `disabled=true` to keep the
|
|
// indicator absent rather than misleading. Returns a stable noop
|
|
// when disabled so call sites keep their stable identity.
|
|
export const useTypingStatusUpdater = (
|
|
mx: MatrixClient,
|
|
roomId: string,
|
|
disabled = false
|
|
): TypingStatusUpdater => {
|
|
const statusSentTsRef = useRef<number>(0);
|
|
|
|
const sendTypingStatus: TypingStatusUpdater = useMemo(() => {
|
|
statusSentTsRef.current = 0;
|
|
if (disabled) {
|
|
return () => {
|
|
/* noop: typing leaks across thread/main boundary by spec */
|
|
};
|
|
}
|
|
return (typing) => {
|
|
if (typing) {
|
|
if (Date.now() - statusSentTsRef.current < TYPING_TIMEOUT_MS) {
|
|
return;
|
|
}
|
|
|
|
mx.sendTyping(roomId, true, TYPING_TIMEOUT_MS);
|
|
const sentTs = Date.now();
|
|
statusSentTsRef.current = sentTs;
|
|
|
|
// Don't believe server will timeout typing status;
|
|
// Clear typing status after timeout if already not;
|
|
setTimeout(() => {
|
|
if (statusSentTsRef.current === sentTs) {
|
|
mx.sendTyping(roomId, false, TYPING_TIMEOUT_MS);
|
|
statusSentTsRef.current = 0;
|
|
}
|
|
}, TYPING_TIMEOUT_MS);
|
|
return;
|
|
}
|
|
|
|
if (Date.now() - statusSentTsRef.current < TYPING_TIMEOUT_MS) {
|
|
mx.sendTyping(roomId, false, TYPING_TIMEOUT_MS);
|
|
}
|
|
statusSentTsRef.current = 0;
|
|
};
|
|
}, [mx, roomId, disabled]);
|
|
|
|
return sendTypingStatus;
|
|
};
|