Add composing notification
Change-Id: I2c052c4395a56ba6acf882cea3be4b82e2fde761
diff --git a/client/src/components/SendMessageForm.tsx b/client/src/components/SendMessageForm.tsx
index 0859d17..c0b9253 100644
--- a/client/src/components/SendMessageForm.tsx
+++ b/client/src/components/SendMessageForm.tsx
@@ -17,11 +17,13 @@
*/
import { InputBase } from '@mui/material';
import { Stack } from '@mui/system';
-import { ChangeEvent, FormEvent, useCallback, useMemo, useState } from 'react';
+import { WebSocketMessageType } from 'jami-web-common';
+import { ChangeEvent, FormEvent, useCallback, useContext, useMemo, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useAuthContext } from '../contexts/AuthProvider';
import { useConversationContext } from '../contexts/ConversationProvider';
+import { WebSocketContext } from '../contexts/WebSocketProvider';
import { ConversationMember } from '../models/conversation-member';
import { translateEnumeration, TranslateEnumerationOptions } from '../utils/translations';
import {
@@ -38,18 +40,46 @@
};
export default function SendMessageForm({ onSend, openFilePicker }: SendMessageFormProps) {
- const { members } = useConversationContext();
+ const webSocket = useContext(WebSocketContext);
+ const { members, conversationId } = useConversationContext();
const [currentMessage, setCurrentMessage] = useState('');
+ const composingNotificationTimeRef = useRef(0);
const placeholder = usePlaceholder(members);
- const handleSubmit = (e: FormEvent<HTMLFormElement>) => {
- e.preventDefault();
- if (currentMessage) {
- onSend(currentMessage);
- setCurrentMessage('');
+ const notifyComposing = useCallback(() => {
+ const currentTime = new Date().getTime();
+ // The daemon automatically turns off "isComposing" after 12 seconds
+ // We ensure it will stay on at least 4 seconds after the last typed character
+ if (currentTime - composingNotificationTimeRef.current > 8000) {
+ composingNotificationTimeRef.current = currentTime;
+ webSocket?.send(WebSocketMessageType.SetIsComposing, { conversationId, isWriting: true });
}
- };
- const handleInputChange = (event: ChangeEvent<HTMLInputElement>) => setCurrentMessage(event.target.value);
+ }, [webSocket, conversationId]);
+
+ const notifyStopcomposing = useCallback(() => {
+ composingNotificationTimeRef.current = 0;
+ webSocket?.send(WebSocketMessageType.SetIsComposing, { conversationId, isWriting: false });
+ }, [webSocket, conversationId]);
+
+ const handleSubmit = useCallback(
+ (e: FormEvent<HTMLFormElement>) => {
+ e.preventDefault();
+ if (currentMessage) {
+ onSend(currentMessage);
+ setCurrentMessage('');
+ notifyStopcomposing();
+ }
+ },
+ [currentMessage, onSend, notifyStopcomposing]
+ );
+
+ const handleInputChange = useCallback(
+ (event: ChangeEvent<HTMLInputElement>) => {
+ setCurrentMessage(event.target.value);
+ notifyComposing();
+ },
+ [notifyComposing]
+ );
const onEmojiSelected = useCallback(
(emoji: string) => setCurrentMessage((currentMessage) => currentMessage + emoji),