Ensure WebSocket client is never undefined
Change-Id: I5f5c34112fa989d6c06697b8a6d46acfbd01008a
diff --git a/client/src/components/SendMessageForm.tsx b/client/src/components/SendMessageForm.tsx
index e5d2371..c938369 100644
--- a/client/src/components/SendMessageForm.tsx
+++ b/client/src/components/SendMessageForm.tsx
@@ -18,12 +18,12 @@
import { InputBase } from '@mui/material';
import { Stack } from '@mui/system';
import { WebSocketMessageType } from 'jami-web-common';
-import { ChangeEvent, FormEvent, useCallback, useContext, useMemo, useRef, useState } from 'react';
+import { ChangeEvent, FormEvent, useCallback, 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 { useWebSocketContext } from '../contexts/WebSocketProvider';
import { ConversationMember } from '../models/conversation-member';
import { translateEnumeration, TranslateEnumerationOptions } from '../utils/translations';
import {
@@ -40,7 +40,7 @@
};
export default function SendMessageForm({ onSend, openFilePicker }: SendMessageFormProps) {
- const webSocket = useContext(WebSocketContext);
+ const webSocket = useWebSocketContext();
const { members, conversationId } = useConversationContext();
const [currentMessage, setCurrentMessage] = useState('');
const composingNotificationTimeRef = useRef(0);
@@ -52,7 +52,7 @@
// 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.ComposingStatus, { conversationId, isWriting: true });
+ webSocket.send(WebSocketMessageType.ComposingStatus, { conversationId, isWriting: true });
}
}, [webSocket, conversationId]);
diff --git a/client/src/contexts/CallManagerProvider.tsx b/client/src/contexts/CallManagerProvider.tsx
index 33b3055..ec68765 100644
--- a/client/src/contexts/CallManagerProvider.tsx
+++ b/client/src/contexts/CallManagerProvider.tsx
@@ -28,7 +28,7 @@
import { SetState, WithChildren } from '../utils/utils';
import { AlertSnackbarContext } from './AlertSnackbarProvider';
import CallProvider, { CallRole } from './CallProvider';
-import { WebSocketContext } from './WebSocketProvider';
+import { useWebSocketContext } from './WebSocketProvider';
export type CallData = {
conversationId: string;
@@ -57,8 +57,8 @@
export default ({ children }: WithChildren) => {
const [callData, setCallData] = useState<CallData>();
- const webSocket = useContext(WebSocketContext);
const { setAlertContent } = useContext(AlertSnackbarContext);
+ const webSocket = useWebSocketContext();
const navigate = useNavigate();
const { data: conversationInfos } = useConversationInfosQuery(callData?.conversationId);
const { data: members } = useMembersQuery(callData?.conversationId);
@@ -81,10 +81,6 @@
}, [callData]);
useEffect(() => {
- if (!webSocket) {
- return;
- }
-
const callBeginListener = ({ conversationId, withVideoOn }: CallBegin) => {
if (callData) {
// TODO: Currently, we display a notification if already in a call.
diff --git a/client/src/contexts/CallProvider.tsx b/client/src/contexts/CallProvider.tsx
index 050ad58..400140c 100644
--- a/client/src/contexts/CallProvider.tsx
+++ b/client/src/contexts/CallProvider.tsx
@@ -26,7 +26,7 @@
import { useAuthContext } from './AuthProvider';
import { CallData, CallManagerContext } from './CallManagerProvider';
import ConditionalContextProvider from './ConditionalContextProvider';
-import { IWebSocketContext, WebSocketContext } from './WebSocketProvider';
+import { IWebSocketContext, useWebSocketContext } from './WebSocketProvider';
export type CallRole = 'caller' | 'receiver';
@@ -83,7 +83,7 @@
export const useCallContext = optionalCallContext.useOptionalContext;
export default ({ children }: WithChildren) => {
- const webSocket = useContext(WebSocketContext);
+ const webSocket = useWebSocketContext();
const { callMembers, callData, exitCall } = useContext(CallManagerContext);
const dependencies = useMemo(
diff --git a/client/src/contexts/ConversationProvider.tsx b/client/src/contexts/ConversationProvider.tsx
index d518c64..097d416 100644
--- a/client/src/contexts/ConversationProvider.tsx
+++ b/client/src/contexts/ConversationProvider.tsx
@@ -16,7 +16,7 @@
* <https://www.gnu.org/licenses/>.
*/
import { ComposingStatus, ConversationInfos, ConversationView, WebSocketMessageType } from 'jami-web-common';
-import { useCallback, useContext, useEffect, useMemo, useState } from 'react';
+import { useCallback, useEffect, useMemo, useState } from 'react';
import LoadingPage from '../components/Loading';
import { createOptionalContext } from '../hooks/createOptionalContext';
@@ -27,7 +27,7 @@
import { useConversationInfosQuery, useMembersQuery } from '../services/conversationQueries';
import { WithChildren } from '../utils/utils';
import { useAuthContext } from './AuthProvider';
-import { WebSocketContext } from './WebSocketProvider';
+import { useWebSocketContext } from './WebSocketProvider';
interface IConversationContext {
conversationId: string;
@@ -46,7 +46,7 @@
urlParams: { conversationId },
} = useUrlParams<ConversationRouteParams>();
const { accountId, account } = useAuthContext();
- const webSocket = useContext(WebSocketContext);
+ const webSocket = useWebSocketContext();
const [composingMembers, setComposingMembers] = useState<ConversationMember[]>([]);
const conversationInfosQuery = useConversationInfosQuery(conversationId!);
@@ -96,7 +96,7 @@
);
useEffect(() => {
- if (!conversationInfos || !conversationId || !webSocket) {
+ if (!conversationInfos || !conversationId) {
return;
}
diff --git a/client/src/contexts/MessengerProvider.tsx b/client/src/contexts/MessengerProvider.tsx
index 2f86ad9..fe96468 100644
--- a/client/src/contexts/MessengerProvider.tsx
+++ b/client/src/contexts/MessengerProvider.tsx
@@ -16,10 +16,10 @@
* <https://www.gnu.org/licenses/>.
*/
import { ConversationMessage, IConversationRequest, WebSocketMessageType } from 'jami-web-common';
-import { createContext, ReactNode, useContext, useEffect, useMemo } from 'react';
+import { createContext, ReactNode, useEffect, useMemo } from 'react';
import { useAddConversationRequestToCache, useRefreshConversationsSummaries } from '../services/conversationQueries';
-import { WebSocketContext } from './WebSocketProvider';
+import { useWebSocketContext } from './WebSocketProvider';
// It is not sure yet we want this context to have no value
// eslint-disable-next-line @typescript-eslint/no-empty-interface
@@ -30,16 +30,12 @@
export const MessengerContext = createContext<IMessengerContext>(defaultMessengerContext);
export default ({ children }: { children: ReactNode }) => {
- const webSocket = useContext(WebSocketContext);
+ const webSocket = useWebSocketContext();
const refreshConversationsSummaries = useRefreshConversationsSummaries();
const addConversationRequestToCache = useAddConversationRequestToCache();
useEffect(() => {
- if (!webSocket) {
- return;
- }
-
const conversationMessageListener = (_data: ConversationMessage) => {
refreshConversationsSummaries();
};
diff --git a/client/src/contexts/WebSocketProvider.tsx b/client/src/contexts/WebSocketProvider.tsx
index 44d54c0..1408953 100644
--- a/client/src/contexts/WebSocketProvider.tsx
+++ b/client/src/contexts/WebSocketProvider.tsx
@@ -15,8 +15,9 @@
* License along with this program. If not, see
* <https://www.gnu.org/licenses/>.
*/
-import { createContext, useEffect, useMemo, useRef } from 'react';
+import { useEffect, useMemo, useRef } from 'react';
+import { createOptionalContext } from '../hooks/createOptionalContext';
import { WebSocketClient } from '../services/WebSocketClient';
import { apiUrl } from '../utils/constants';
import { WithChildren } from '../utils/utils';
@@ -28,7 +29,8 @@
send: WebSocketClient['send'];
}
-export const WebSocketContext = createContext<IWebSocketContext | undefined>(undefined);
+const optionalWebSocketContext = createOptionalContext<IWebSocketContext>('WebSocketContext');
+export const useWebSocketContext = optionalWebSocketContext.useOptionalContext;
export default ({ children }: WithChildren) => {
const webSocketClientRef = useRef<WebSocketClient>(new WebSocketClient());
@@ -39,7 +41,7 @@
webSocketClientRef.current.connect(apiUrl, accessToken);
}, [accessToken]);
- const value: IWebSocketContext = useMemo(
+ const value = useMemo(
() => ({
bind: webSocketClientRef.current.bind.bind(webSocketClientRef.current),
unbind: webSocketClientRef.current.unbind.bind(webSocketClientRef.current),
@@ -48,5 +50,7 @@
[]
);
- return <WebSocketContext.Provider value={value}>{children}</WebSocketContext.Provider>;
+ return (
+ <optionalWebSocketContext.Context.Provider value={value}>{children}</optionalWebSocketContext.Context.Provider>
+ );
};
diff --git a/client/src/pages/ChatInterface.tsx b/client/src/pages/ChatInterface.tsx
index fa428ac..4ac8037 100644
--- a/client/src/pages/ChatInterface.tsx
+++ b/client/src/pages/ChatInterface.tsx
@@ -18,7 +18,7 @@
import { Box, Divider, Fade, Stack, Typography } from '@mui/material';
import { motion } from 'framer-motion';
import { ConversationMessage, Message, WebSocketMessageType } from 'jami-web-common';
-import { useCallback, useContext, useEffect, useMemo, useState } from 'react';
+import { useCallback, useEffect, useMemo, useState } from 'react';
import { useDropzone } from 'react-dropzone';
import { useTranslation } from 'react-i18next';
@@ -28,14 +28,14 @@
import { FileDragOverlay } from '../components/Overlay';
import SendMessageForm from '../components/SendMessageForm';
import { useConversationContext } from '../contexts/ConversationProvider';
-import { WebSocketContext } from '../contexts/WebSocketProvider';
+import { useWebSocketContext } from '../contexts/WebSocketProvider';
import { ConversationMember } from '../models/conversation-member';
import { useMessagesQuery, useSendMessageMutation } from '../services/conversationQueries';
import { FileHandler } from '../utils/files';
import { translateEnumeration, TranslateEnumerationOptions } from '../utils/translations';
const ChatInterface = () => {
- const webSocket = useContext(WebSocketContext);
+ const webSocket = useWebSocketContext();
const { conversationId } = useConversationContext();
const [messages, setMessages] = useState<Message[]>([]);
const [isLoading, setIsLoading] = useState(true);
@@ -90,18 +90,16 @@
const sendMessage = useCallback((message: string) => sendMessageMutation.mutate(message), [sendMessageMutation]);
useEffect(() => {
- if (webSocket) {
- const conversationMessageListener = (data: ConversationMessage) => {
- console.log('newMessage');
- setMessages((messages) => addMessage(messages, data.message));
- };
+ const conversationMessageListener = (data: ConversationMessage) => {
+ console.log('newMessage');
+ setMessages((messages) => addMessage(messages, data.message));
+ };
- webSocket.bind(WebSocketMessageType.ConversationMessage, conversationMessageListener);
+ webSocket.bind(WebSocketMessageType.ConversationMessage, conversationMessageListener);
- return () => {
- webSocket.unbind(WebSocketMessageType.ConversationMessage, conversationMessageListener);
- };
- }
+ return () => {
+ webSocket.unbind(WebSocketMessageType.ConversationMessage, conversationMessageListener);
+ };
}, [webSocket]);
if (isLoading) {