diff --git a/src/events/onBroadcastFinished.tsx b/src/events/onBroadcastFinished.tsx index 5f3476e..d39e334 100644 --- a/src/events/onBroadcastFinished.tsx +++ b/src/events/onBroadcastFinished.tsx @@ -1,9 +1,10 @@ import type { MutableRefObject } from 'react'; +import type { EmitterSubscription } from 'react-native'; import nativeEmitter from '../native-messaging/emitter'; -export function setupListener(_webViewRef: MutableRefObject) { +export function setupListener(_webViewRef: MutableRefObject):EmitterSubscription { // Resolve promise when SDP offer is available - nativeEmitter.addListener('onBroadcastFinished', () => { + return nativeEmitter.addListener('onBroadcastFinished', () => { console.log(`Broadcast finished`); _webViewRef.current.injectJavaScript( `window.bbbMobileScreenShareBroadcastFinishedCallback && window.bbbMobileScreenShareBroadcastFinishedCallback();` diff --git a/src/events/onScreenShareLocalIceCandidate.tsx b/src/events/onScreenShareLocalIceCandidate.tsx index 41f5a0f..ef0936f 100644 --- a/src/events/onScreenShareLocalIceCandidate.tsx +++ b/src/events/onScreenShareLocalIceCandidate.tsx @@ -1,9 +1,10 @@ import type { MutableRefObject } from 'react'; +import type { EmitterSubscription } from 'react-native'; import nativeEmitter from '../native-messaging/emitter'; -export function setupListener(_webViewRef: MutableRefObject) { +export function setupListener(_webViewRef: MutableRefObject):EmitterSubscription { // Resolve promise when SDP offer is available - nativeEmitter.addListener( + return nativeEmitter.addListener( 'onScreenShareLocalIceCandidate', (jsonEncodedIceCandidate) => { let iceCandidate = JSON.parse(jsonEncodedIceCandidate); diff --git a/src/events/onScreenShareSignalingStateChange.tsx b/src/events/onScreenShareSignalingStateChange.tsx index 34ca2f9..e5740c0 100644 --- a/src/events/onScreenShareSignalingStateChange.tsx +++ b/src/events/onScreenShareSignalingStateChange.tsx @@ -1,9 +1,10 @@ import type { MutableRefObject } from 'react'; +import type { EmitterSubscription } from 'react-native'; import nativeEmitter from '../native-messaging/emitter'; -export function setupListener(_webViewRef: MutableRefObject) { +export function setupListener(_webViewRef: MutableRefObject):EmitterSubscription { // Resolve promise when SDP offer is available - nativeEmitter.addListener('onScreenShareSignalingStateChange', (newState) => { + return nativeEmitter.addListener('onScreenShareSignalingStateChange', (newState) => { console.log(`Temos um novo state: ${newState}`); _webViewRef.current.injectJavaScript( `window.bbbMobileScreenShareSignalingStateChangeCallback && window.bbbMobileScreenShareSignalingStateChangeCallback(${JSON.stringify( diff --git a/src/index.tsx b/src/index.tsx index 56d6498..cd14875 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,4 +1,4 @@ -import { Platform, ViewStyle } from 'react-native'; +import { EmitterSubscription, Platform, ViewStyle } from 'react-native'; import React, { useEffect, useRef } from 'react'; import BBBN_SystemBroadcastPicker from './native-components/BBBN_SystemBroadcastPicker'; import { WebView } from 'react-native-webview'; @@ -14,6 +14,10 @@ type BigbluebuttonMobileSdkProps = { onSuccess?: any; }; +const data = { + instances: 0 +} + const renderPlatformSpecificComponents = () => Platform.select({ ios: , @@ -27,11 +31,27 @@ export const BigBlueButtonMobile = ({ onSuccess, }: BigbluebuttonMobileSdkProps) => { const webViewRef = useRef(null); + const thisInstanceId = ++data.instances; + + // console.log("XXX - ", thisInstanceId); useEffect(() => { - onScreenShareLocalIceCandidate.setupListener(webViewRef); - onScreenShareSignalingStateChange.setupListener(webViewRef); - onBroadcastFinished.setupListener(webViewRef); + const logPrefix = `[${thisInstanceId}] - ${url.substring(8, 16)}`; + + console.log(`${logPrefix} - addingListeners`); + const listeners:EmitterSubscription[] = []; + listeners.push(onScreenShareLocalIceCandidate.setupListener(webViewRef)); + listeners.push(onScreenShareSignalingStateChange.setupListener(webViewRef)); + listeners.push(onBroadcastFinished.setupListener(webViewRef)); + + return () => { + console.log(`${logPrefix} - Removing listeners`); + + listeners.forEach( (listener, index) => { + console.log(`${logPrefix} - Removing listener ${index}`); + listener.remove(); + } ); + } }, [webViewRef]); return ( @@ -43,7 +63,7 @@ export const BigBlueButtonMobile = ({ source={{ uri: url }} style={{ ...style }} contentMode={'mobile'} - onMessage={(msg) => handleWebviewMessage(webViewRef, msg)} + onMessage={(msg) => handleWebviewMessage(thisInstanceId, webViewRef, msg)} applicationNameForUserAgent="BBBMobile" allowsInlineMediaPlayback={true} onLoadEnd={(content: any) => { diff --git a/src/methods/addScreenShareRemoteIceCandidate.tsx b/src/methods/addScreenShareRemoteIceCandidate.tsx index cdb9a6a..29ff4f4 100644 --- a/src/methods/addScreenShareRemoteIceCandidate.tsx +++ b/src/methods/addScreenShareRemoteIceCandidate.tsx @@ -14,14 +14,14 @@ nativeEmitter.addListener('onAddScreenShareRemoteIceCandidateCompleted', () => { }); // Entry point of this method -function addScreenShareRemoteIceCandidate(remoteCandidateJson: string) { +function addScreenShareRemoteIceCandidate(instanceId: Number, remoteCandidateJson: string) { return new Promise((res, rej) => { // store the resolver for later call (when event is received) resolve = res; try { console.log( - `>nativeAddScreenShareRemoteIceCandidate ${remoteCandidateJson}` + `[${instanceId}] - >nativeAddScreenShareRemoteIceCandidate ${remoteCandidateJson}` ); // call native swift method that triggers the broadcast popup nativeAddScreenShareRemoteIceCandidate(remoteCandidateJson); diff --git a/src/methods/createFullAudioOffer.tsx b/src/methods/createFullAudioOffer.tsx index fe0b4a7..b99c5d8 100644 --- a/src/methods/createFullAudioOffer.tsx +++ b/src/methods/createFullAudioOffer.tsx @@ -14,13 +14,13 @@ nativeEmitter.addListener('onFullAudioOfferCreated', (sdp) => { }); // Entry point of this method -function createFullAudioOffer() { +function createFullAudioOffer(instanceId: Number) { return new Promise((res, rej) => { // store the resolver for later call (when event is received) resolve = res; try { - console.log(`>nativeCreateFullAudioOffer`); + console.log(`[${instanceId}] - >nativeCreateFullAudioOffer`); // call native swift method that triggers the broadcast popup nativeCreateFullAudioOffer(); } catch (e) { diff --git a/src/methods/createScreenShareOffer.tsx b/src/methods/createScreenShareOffer.tsx index 16378be..5f80a0a 100644 --- a/src/methods/createScreenShareOffer.tsx +++ b/src/methods/createScreenShareOffer.tsx @@ -14,13 +14,13 @@ nativeEmitter.addListener('onScreenShareOfferCreated', (sdp) => { }); // Entry point of this method -function createScreenShareOffer() { +function createScreenShareOffer(instanceId: Number) { return new Promise((res, rej) => { // store the resolver for later call (when event is received) resolve = res; try { - console.log(`>nativeCreateScreenShareOffer`); + console.log(`[${instanceId}] - >nativeCreateScreenShareOffer`); // call native swift method that triggers the broadcast popup nativeCreateScreenShareOffer(); } catch (e) { diff --git a/src/methods/initializeScreenShare.tsx b/src/methods/initializeScreenShare.tsx index 5b4e72a..8bdb6ca 100644 --- a/src/methods/initializeScreenShare.tsx +++ b/src/methods/initializeScreenShare.tsx @@ -19,14 +19,14 @@ nativeEmitter.addListener('onBroadcastStarted', () => { }); // Entry point of this method -function initializeScreenShare() { +function initializeScreenShare(instanceId: Number) { return new Promise((res, rej) => { // store the resolver for later call (when event is received) resolve = res; try { // call native swift method that triggers the broadcast popup - console.log(`>nativeInitializeScreenShare`); + console.log(`[${instanceId}] - >nativeInitializeScreenShare`); nativeInitializeScreenShare(); } catch (e) { rej(`Call to nativeInitializeScreenShare failed zzy`); diff --git a/src/methods/setFullAudioRemoteSDP.tsx b/src/methods/setFullAudioRemoteSDP.tsx index a830ff4..324b410 100644 --- a/src/methods/setFullAudioRemoteSDP.tsx +++ b/src/methods/setFullAudioRemoteSDP.tsx @@ -14,13 +14,13 @@ nativeEmitter.addListener('onSetFullAudioRemoteSDPCompleted', () => { }); // Entry point of this method -function setFullAudioRemoteSDP(remoteSdp: string) { +function setFullAudioRemoteSDP(instanceId: Number, remoteSdp: string) { return new Promise((res, rej) => { // store the resolver for later call (when event is received) resolve = res; try { - console.log(`>nativeSetFullAudioRemoteSDP ${remoteSdp}`); + console.log(`[${instanceId}] - >nativeSetFullAudioRemoteSDP ${remoteSdp}`); // call native swift method that triggers the broadcast popup nativeSetFullAudioRemoteSDP(remoteSdp); } catch (e) { diff --git a/src/methods/setScreenShareRemoteSDP.tsx b/src/methods/setScreenShareRemoteSDP.tsx index 706fc13..2347bfe 100644 --- a/src/methods/setScreenShareRemoteSDP.tsx +++ b/src/methods/setScreenShareRemoteSDP.tsx @@ -14,13 +14,13 @@ nativeEmitter.addListener('onSetScreenShareRemoteSDPCompleted', () => { }); // Entry point of this method -function setScreenShareRemoteSDP(remoteSdp: string) { +function setScreenShareRemoteSDP(instanceId: Number, remoteSdp: string) { return new Promise((res, rej) => { // store the resolver for later call (when event is received) resolve = res; try { - console.log(`>nativeSetScreenShareRemoteSDP ${remoteSdp}`); + console.log(`[${instanceId}] - >nativeSetScreenShareRemoteSDP ${remoteSdp}`); // call native swift method that triggers the broadcast popup nativeSetScreenShareRemoteSDP(remoteSdp); } catch (e) { diff --git a/src/webview/message-handler.tsx b/src/webview/message-handler.tsx index 91c9ca4..8616d43 100644 --- a/src/webview/message-handler.tsx +++ b/src/webview/message-handler.tsx @@ -8,13 +8,14 @@ import addScreenShareRemoteIceCandidate from '../methods/addScreenShareRemoteIce import createFullAudioOffer from '../methods/createFullAudioOffer'; function observePromiseResult( + instanceId: Number, webViewRef: MutableRefObject, sequence: number, prom: Promise ) { prom .then((result: any) => { - console.log(`Promise ${sequence} resolved!`, result); + console.log(`[${instanceId}] - Promise ${sequence} resolved!`, result); webViewRef.current.injectJavaScript( `window.nativeMethodCallResult(${sequence}, true ${ result ? ',' + JSON.stringify(result) : '' @@ -22,7 +23,7 @@ function observePromiseResult( ); }) .catch((exception: any) => { - console.error(`Promise ${sequence} failed!`, exception); + console.error(`[${instanceId}] - Promise ${sequence} failed!`, exception); webViewRef.current.injectJavaScript( `window.nativeMethodCallResult(${sequence}, false ${ exception ? ',' + JSON.stringify(exception) : '' @@ -32,41 +33,45 @@ function observePromiseResult( } export function handleWebviewMessage( + instanceId: Number, webViewRef: MutableRefObject, event: WebViewMessageEvent ) { const stringData = event?.nativeEvent?.data; + console.log("handleWebviewMessage - ", instanceId); + const data = JSON.parse(stringData); if (data?.method && data?.sequence) { let promise; switch (data?.method) { case 'initializeScreenShare': - promise = initializeScreenShare(); + promise = initializeScreenShare(instanceId); break; case 'createFullAudioOffer': - promise = createFullAudioOffer(); + promise = createFullAudioOffer(instanceId); break; case 'createScreenShareOffer': - promise = createScreenShareOffer(); + promise = createScreenShareOffer(instanceId); break; case 'setScreenShareRemoteSDP': - promise = setScreenShareRemoteSDP(data?.arguments[0].sdp); + promise = setScreenShareRemoteSDP(instanceId, data?.arguments[0].sdp); break; case 'setFullAudioRemoteSDP': - promise = setFullAudioRemoteSDP(data?.arguments[0].sdp); + promise = setFullAudioRemoteSDP(instanceId, data?.arguments[0].sdp); break; case 'addRemoteIceCandidate': promise = addScreenShareRemoteIceCandidate( + instanceId, JSON.stringify(data?.arguments[0]) ); break; default: - throw `Unknown method ${data?.method}`; + throw `[${instanceId}] - Unknown method ${data?.method}`; } - observePromiseResult(webViewRef, data.sequence, promise); + observePromiseResult(instanceId, webViewRef, data.sequence, promise); } else { - console.log(`Ignoring unknown message: $stringData`); + console.log(`[${instanceId}] - Ignoring unknown message: $stringData`); } }