Add unbind function to WebSocketContext
Change WebSocketCallbacks to have sets of callbacks instead of arrays.
Change-Id: I48439d0ff9b8188f47e0530d7d91f78c6fae8868
diff --git a/client/src/contexts/WebRTCProvider.tsx b/client/src/contexts/WebRTCProvider.tsx
index 7dc1611..4801387 100644
--- a/client/src/contexts/WebRTCProvider.tsx
+++ b/client/src/contexts/WebRTCProvider.tsx
@@ -16,7 +16,13 @@
* <https://www.gnu.org/licenses/>.
*/
-import { WebSocketMessageType } from 'jami-web-common';
+import {
+ AccountTextMessage,
+ WebRTCAnswerMessage,
+ WebRTCIceCandidate,
+ WebRTCOfferMessage,
+ WebSocketMessageType,
+} from 'jami-web-common';
import React, { createContext, useCallback, useContext, useEffect, useRef, useState } from 'react';
import { WithChildren } from '../utils/utils';
@@ -178,7 +184,7 @@
return;
}
- webSocket.bind(WebSocketMessageType.WebRTCOffer, async (data) => {
+ const webRTCOfferListener = async (data: AccountTextMessage<WebRTCOfferMessage>) => {
if (webRTCConnection) {
await webRTCConnection.setRemoteDescription(new RTCSessionDescription(data.message.sdp));
const mySdp = await webRTCConnection.createAnswer({
@@ -194,17 +200,27 @@
},
});
}
- });
+ };
- webSocket.bind(WebSocketMessageType.WebRTCAnswer, async (data) => {
+ const webRTCAnswerListener = async (data: AccountTextMessage<WebRTCAnswerMessage>) => {
await webRTCConnection.setRemoteDescription(new RTCSessionDescription(data.message.sdp));
console.log('get answer');
- });
+ };
- webSocket.bind(WebSocketMessageType.IceCandidate, async (data) => {
+ const iceCandidateListener = async (data: AccountTextMessage<WebRTCIceCandidate>) => {
await webRTCConnection.addIceCandidate(new RTCIceCandidate(data.message.candidate));
console.log('webRTCConnection : candidate add success');
- });
+ };
+
+ webSocket.bind(WebSocketMessageType.WebRTCOffer, webRTCOfferListener);
+ webSocket.bind(WebSocketMessageType.WebRTCAnswer, webRTCAnswerListener);
+ webSocket.bind(WebSocketMessageType.IceCandidate, iceCandidateListener);
+
+ return () => {
+ webSocket.unbind(WebSocketMessageType.WebRTCOffer, webRTCOfferListener);
+ webSocket.unbind(WebSocketMessageType.WebRTCAnswer, webRTCAnswerListener);
+ webSocket.unbind(WebSocketMessageType.IceCandidate, iceCandidateListener);
+ };
}, [account, contactId, webSocket, webRTCConnection]);
const setAudioStatus = useCallback((isOn: boolean) => {
diff --git a/client/src/contexts/WebSocketProvider.tsx b/client/src/contexts/WebSocketProvider.tsx
index e6e246b..b90f609 100644
--- a/client/src/contexts/WebSocketProvider.tsx
+++ b/client/src/contexts/WebSocketProvider.tsx
@@ -15,16 +15,29 @@
* License along with this program. If not, see
* <https://www.gnu.org/licenses/>.
*/
-import { WebSocketCallbacks, WebSocketMessage, WebSocketMessageTable, WebSocketMessageType } from 'jami-web-common';
+import {
+ buildWebSocketCallbacks,
+ WebSocketCallbacks,
+ WebSocketMessage,
+ WebSocketMessageTable,
+ WebSocketMessageType,
+} from 'jami-web-common';
import { createContext, useCallback, useEffect, useRef, useState } from 'react';
import { apiUrl } from '../utils/constants';
import { WithChildren } from '../utils/utils';
import { useAuthContext } from './AuthProvider';
+type BindFunction = <T extends WebSocketMessageType>(
+ type: T,
+ callback: (data: WebSocketMessageTable[T]) => void
+) => void;
+type SendFunction = <T extends WebSocketMessageType>(type: T, data: WebSocketMessageTable[T]) => void;
+
export interface IWebSocketContext {
- bind: <T extends WebSocketMessageType>(type: T, callback: (data: WebSocketMessageTable[T]) => void) => void;
- send: <T extends WebSocketMessageType>(type: T, data: WebSocketMessageTable[T]) => void;
+ bind: BindFunction;
+ unbind: BindFunction;
+ send: SendFunction;
}
export const WebSocketContext = createContext<IWebSocketContext | undefined>(undefined);
@@ -32,29 +45,28 @@
export default ({ children }: WithChildren) => {
const [isConnected, setIsConnected] = useState(false);
const webSocketRef = useRef<WebSocket>();
- const callbacksRef = useRef<WebSocketCallbacks>({
- [WebSocketMessageType.ConversationMessage]: [],
- [WebSocketMessageType.ConversationView]: [],
- [WebSocketMessageType.WebRTCOffer]: [],
- [WebSocketMessageType.WebRTCAnswer]: [],
- [WebSocketMessageType.IceCandidate]: [],
- });
+ const callbacksRef = useRef<WebSocketCallbacks>(buildWebSocketCallbacks());
const { token: accessToken } = useAuthContext();
- const context: IWebSocketContext = {
- bind: useCallback((type, callback) => {
- callbacksRef.current[type].push(callback);
- }, []),
- send: useCallback(
- (type, data) => {
- if (isConnected) {
- webSocketRef.current?.send(JSON.stringify({ type, data }));
- }
- },
- [isConnected]
- ),
- };
+ const bind: BindFunction = useCallback((type, callback) => {
+ const callbacks = callbacksRef.current[type];
+ callbacks.add(callback);
+ }, []);
+
+ const unbind: BindFunction = useCallback((type, callback) => {
+ const callbacks = callbacksRef.current[type];
+ callbacks.delete(callback);
+ }, []);
+
+ const send: SendFunction = useCallback(
+ (type, data) => {
+ if (isConnected) {
+ webSocketRef.current?.send(JSON.stringify({ type, data }));
+ }
+ },
+ [isConnected]
+ );
const connect = useCallback(() => {
const url = new URL(apiUrl);
@@ -72,7 +84,7 @@
console.debug('WebSocket disconnected');
setIsConnected(false);
for (const callbacks of Object.values(callbacksRef.current)) {
- callbacks.length = 0;
+ callbacks.clear();
}
setTimeout(connect, 1000);
};
@@ -119,5 +131,19 @@
useEffect(connect, [connect]);
- return <WebSocketContext.Provider value={isConnected ? context : undefined}>{children}</WebSocketContext.Provider>;
+ return (
+ <WebSocketContext.Provider
+ value={
+ isConnected
+ ? {
+ bind,
+ unbind,
+ send,
+ }
+ : undefined
+ }
+ >
+ {children}
+ </WebSocketContext.Provider>
+ );
};