From cd80995c522d14e464028fa62cee4930ce3dc0a9 Mon Sep 17 00:00:00 2001 From: zhanim-tdl Date: Mon, 3 Nov 2025 13:00:26 +0100 Subject: [PATCH] fix: added more error handling scenarios --- ExampleApp/src/App.tsx | 39 ++++++++++++------- .../library/CustomTwilioVideoView.java | 12 +++++- ios/RCTTWVideoModule.m | 6 +++ 3 files changed, 42 insertions(+), 15 deletions(-) diff --git a/ExampleApp/src/App.tsx b/ExampleApp/src/App.tsx index dee7822a..7e14c149 100644 --- a/ExampleApp/src/App.tsx +++ b/ExampleApp/src/App.tsx @@ -180,24 +180,27 @@ const Example = () => { setStatus("connected"); }; - const _onRoomDidDisconnect = () => { + const _onRoomDidDisconnect = (event: any) => { + if (event.error) { + setErrorMessage(_formatErrorMessage(event)); + } resetStates(); }; const _onRoomDidFailToConnect = (event: any) => { setStatus("disconnected"); - - let errorMsg = event?.error || "Failed to connect to room"; - + setErrorMessage(_formatErrorMessage(event)); + }; + + const _formatErrorMessage = (event: any) => { + let errorMsg = event?.error || "Something went wrong"; if (event?.code) { errorMsg += `\n\nError Code: ${event.code}`; } - if (event?.errorExplanation) { errorMsg += `\n\nDetails: ${event.errorExplanation}`; } - - setErrorMessage(errorMsg); + return errorMsg; }; const _onParticipantAddedVideoTrack = ({ participant, track }: any) => { @@ -217,6 +220,16 @@ const Example = () => { }); }; + const _onRoomIsReconnecting = (event: any) => { + setStatus("reconnecting"); + _log(`Room Is Reconnecting ${event.roomName} ${event.error}`); + }; + + const _onRoomDidReconnect = (event: any) => { + setStatus("connected"); + _log(`Room Did Reconnect ${event.roomName}`); + }; + return ( {status === "disconnected" && ( @@ -235,7 +248,7 @@ const Example = () => { )} - {(status === "connected" || status === "connecting") && ( + {(status === "connected" || status === "connecting" || status === "reconnecting") && ( Room Name: {roomDetails.roomName} @@ -286,10 +299,10 @@ const Example = () => { onNetworkQualityLevelsChanged={e => _log(`Network Quality ${e.participant.identity || 'local'} -> ${e.quality}`)} onDominantSpeakerDidChange={e => _log(`Dominant Speaker -> ${e.participant?.identity || 'none'}`)} onDataTrackMessageReceived={e => _log(`Data Track Message ${e.message}`)} - onRoomIsReconnecting={e => _log(`Room Is Reconnecting ${e.roomName} ${e.error}`)} - onRoomDidReconnect={e => _log(`Room Did Reconnect ${e.roomName}`)} + onRoomIsReconnecting={_onRoomIsReconnecting} + onRoomDidReconnect={_onRoomDidReconnect} /> - + { Connection Error {errorMessage} - setErrorMessage("")} > Close diff --git a/android/src/main/java/com/twiliorn/library/CustomTwilioVideoView.java b/android/src/main/java/com/twiliorn/library/CustomTwilioVideoView.java index 101d0592..d15e95b8 100644 --- a/android/src/main/java/com/twiliorn/library/CustomTwilioVideoView.java +++ b/android/src/main/java/com/twiliorn/library/CustomTwilioVideoView.java @@ -29,11 +29,11 @@ import static com.twiliorn.library.CustomTwilioVideoView.Events.ON_PARTICIPANT_REMOVED_AUDIO_TRACK; import static com.twiliorn.library.CustomTwilioVideoView.Events.ON_PARTICIPANT_REMOVED_DATA_TRACK; import static com.twiliorn.library.CustomTwilioVideoView.Events.ON_PARTICIPANT_REMOVED_VIDEO_TRACK; +import static com.twiliorn.library.CustomTwilioVideoView.Events.ON_RECONNECTED; +import static com.twiliorn.library.CustomTwilioVideoView.Events.ON_RECONNECTING; import static com.twiliorn.library.CustomTwilioVideoView.Events.ON_SCREEN_SHARE_CHANGED; import static com.twiliorn.library.CustomTwilioVideoView.Events.ON_STATS_RECEIVED; import static com.twiliorn.library.CustomTwilioVideoView.Events.ON_VIDEO_CHANGED; -import static com.twiliorn.library.CustomTwilioVideoView.Events.ON_RECONNECTING; -import static com.twiliorn.library.CustomTwilioVideoView.Events.ON_RECONNECTED; import android.app.Activity; import android.content.BroadcastReceiver; @@ -549,6 +549,14 @@ public void connectToRoom() { /* * Create a VideoClient allowing you to connect to a Room */ + + if (this.accessToken == null || this.accessToken.isEmpty()) { + WritableMap event = new WritableNativeMap(); + event.putString("error", "Access token is required"); + pushEvent(CustomTwilioVideoView.this, ON_CONNECT_FAILURE, event); + return; + } + ConnectOptions.Builder connectOptionsBuilder = new ConnectOptions.Builder(this.accessToken); if (this.roomName != null) { diff --git a/ios/RCTTWVideoModule.m b/ios/RCTTWVideoModule.m index afc58027..a1d5d179 100644 --- a/ios/RCTTWVideoModule.m +++ b/ios/RCTTWVideoModule.m @@ -668,6 +668,12 @@ - (NSMutableDictionary *)convertLocalVideoTrackStats: enableNetworkQualityReporting dominantSpeakerEnabled : (BOOL) dominantSpeakerEnabled cameraType : (NSString *) cameraType) { + // Guard against missing access token + if (accessToken == nil || [accessToken length] == 0) { + NSMutableDictionary *body = [@{ @"error": @"Access token is required" } mutableCopy]; + [self sendEventCheckingListenerWithName:roomDidFailToConnect body:body]; + return; + } // Only create video track if enabled during connect if (enableVideo) { [self _createVideoTrack:cameraType];