Skip to content

Commit 3c34548

Browse files
committed
feat: added registered call check on turbomodule side
1 parent 799e1ec commit 3c34548

File tree

11 files changed

+64
-85
lines changed

11 files changed

+64
-85
lines changed

packages/react-native-callingx/android/src/main/java/com/callingx/CallService.kt

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,3 @@
1-
/*
2-
* Copyright 2023 The Android Open Source Project
3-
*
4-
* Licensed under the Apache License, Version 2.0 (the "License");
5-
* you may not use this file except in compliance with the License.
6-
* You may obtain a copy of the License at
7-
*
8-
* https://www.apache.org/licenses/LICENSE-2.0
9-
*
10-
* Unless required by applicable law or agreed to in writing, software
11-
* distributed under the License is distributed on an "AS IS" BASIS,
12-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13-
* See the License for the specific language governing permissions and
14-
* limitations under the License.
15-
*/
16-
171
package com.callingx
182

193
import CallRepository
@@ -26,7 +10,6 @@ import android.os.Bundle
2610
import android.os.IBinder
2711
import android.telecom.DisconnectCause
2812
import android.util.Log
29-
import androidx.annotation.RequiresApi
3013
import com.callingx.model.Call
3114
import com.callingx.model.CallAction
3215
import com.callingx.notifications.CallNotificationManager
@@ -270,6 +253,11 @@ class CallService : Service(), CallRepository.Listener {
270253
}
271254
}
272255

256+
fun isCallRegistered(callId: String): Boolean {
257+
val currentCall = callRepository.currentCall.value
258+
return currentCall is Call.Registered && currentCall.id == callId
259+
}
260+
273261
public fun processAction(action: CallAction) {
274262
Log.d(TAG, "[service] processAction: Processing action: ${action::class.simpleName}")
275263
val currentCall = callRepository.currentCall.value

packages/react-native-callingx/android/src/main/java/com/callingx/CallingxModule.kt

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import android.os.IBinder
1212
import android.telecom.DisconnectCause
1313
import android.util.Log
1414
import androidx.core.content.ContextCompat
15+
import androidx.core.net.toUri
1516
import com.callingx.model.CallAction
1617
import com.callingx.notifications.NotificationChannelsManager
1718
import com.callingx.notifications.NotificationsConfig
@@ -25,7 +26,6 @@ import com.facebook.react.bridge.WritableMap
2526
import com.facebook.react.bridge.WritableNativeArray
2627
import com.facebook.react.module.annotations.ReactModule
2728
import com.facebook.react.modules.core.DeviceEventManagerModule
28-
import androidx.core.net.toUri
2929

3030
@ReactModule(name = CallingxModule.NAME)
3131
class CallingxModule(reactContext: ReactApplicationContext) : NativeCallingxSpec(reactContext) {
@@ -252,6 +252,11 @@ class CallingxModule(reactContext: ReactApplicationContext) : NativeCallingxSpec
252252
executeServiceAction(action, promise)
253253
}
254254

255+
override fun isCallRegistered(callId: String): Boolean {
256+
Log.d(TAG, "[module] isCallRegistered: Checking if call is registered: $callId")
257+
return callService?.isCallRegistered(callId) ?: false
258+
}
259+
255260
override fun setMutedCall(callId: String, isMuted: Boolean, promise: Promise) {
256261
Log.d(TAG, "[module] setMutedCall: Setting muted call: $callId, $isMuted")
257262
val action = CallAction.ToggleMute(isMuted)
@@ -475,6 +480,11 @@ class CallingxModule(reactContext: ReactApplicationContext) : NativeCallingxSpec
475480
val action = intent.action
476481
val callId = intent.getStringExtra(EXTRA_CALL_ID)
477482

483+
Log.d(
484+
TAG,
485+
"[module] onReceive: Received intent: $action callId: $callId callService: ${callService != null}"
486+
)
487+
478488
if (action == SERVICE_READY_ACTION) {
479489
Log.d(TAG, "[module] onReceive: Service is ready, initiating binding")
480490
bindToServiceIfNeeded()
@@ -486,10 +496,6 @@ class CallingxModule(reactContext: ReactApplicationContext) : NativeCallingxSpec
486496
return
487497
}
488498

489-
Log.d(
490-
TAG,
491-
"[module] onReceive: Received intent: $action callId: $callId callService: ${callService != null}"
492-
)
493499
val params = Arguments.createMap()
494500
if (callId != null) {
495501
params.putString("callId", callId)

packages/react-native-callingx/android/src/main/java/com/callingx/notifications/NotificationsConfig.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ object NotificationsConfig {
118118
id = channel.getString("id") ?: "",
119119
name = channel.getString("name") ?: "",
120120
sound = channel.getString("sound"),
121-
vibration = channel.getBoolean("vibration"),
121+
vibration = channel.hasKey("vibration") && channel.getBoolean("vibration") ?: false,
122122
importance = importance,
123123
)
124124
}

packages/react-native-callingx/ios/Callingx.mm

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,8 @@ + (void)endCall:(NSString *)callId reason:(int)reason {
355355
default:
356356
break;
357357
}
358+
359+
[uuidStorage removeCid:callId];
358360
}
359361

360362
+ (BOOL)requiresMainQueueSetup {
@@ -744,6 +746,20 @@ - (void)endCall:(nonnull NSString *)callId
744746
resolve(@YES);
745747
}
746748

749+
- (NSNumber *)isCallRegistered:(nonnull NSString *)callId {
750+
NSUUID *uuid = [uuidStorage getUUIDForCid:callId];
751+
if (uuid == nil) return @NO;
752+
753+
CXCallObserver *observer = [[CXCallObserver alloc] init];
754+
for (CXCall *call in observer.calls) {
755+
if ([call.UUID isEqual:uuid]) {
756+
return @YES;
757+
}
758+
}
759+
760+
return @NO;
761+
}
762+
747763
- (void)setCurrentCallActive:(nonnull NSString *)callId
748764
resolve:(nonnull RCTPromiseResolveBlock)resolve
749765
reject:(nonnull RCTPromiseRejectBlock)reject {

packages/react-native-callingx/src/CallingxModule.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,10 @@ class CallingxModule implements ICallingxModule {
184184
return NativeCallingModule.endCallWithReason(callId, reasons[reason]);
185185
}
186186

187+
isCallRegistered(callId: string): boolean {
188+
return NativeCallingModule.isCallRegistered(callId);
189+
}
190+
187191
setMutedCall(callId: string, isMuted: boolean): Promise<void> {
188192
return NativeCallingModule.setMutedCall(callId, isMuted);
189193
}

packages/react-native-callingx/src/spec/NativeCallingx.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ export interface Spec extends TurboModule {
7676
}
7777
): Promise<void>;
7878

79+
isCallRegistered(callId: string): boolean;
80+
7981
endCallWithReason(callId: string, reason: number): Promise<void>;
8082

8183
endCall(callId: string): Promise<void>;

packages/react-native-callingx/src/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ export interface ICallingxModule {
3939
displayOptions?: InfoDisplayOptions
4040
): Promise<void>;
4141

42+
isCallRegistered(callId: string): boolean;
43+
4244
endCallWithReason(callId: string, reason: EndCallReason): Promise<void>;
4345

4446
setMutedCall(callId: string, isMuted: boolean): Promise<void>;

packages/react-native-sdk/src/hooks/push/useCallingExpWithCallingStateEffect.ts

Lines changed: 16 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import {
55
} from '@stream-io/video-client';
66
import { useCall, useCallStateHooks } from '@stream-io/video-react-bindings';
77
import { useEffect, useRef } from 'react';
8-
import { voipPushNotificationCallCId$ } from '../../utils/push/internal/rxSubjects';
98
import { getCallingxLibIfAvailable } from '../../utils/push/libs/callingx';
109

1110
//calling state methods are not exhaustive, so we need to add more methods to cover all the cases
@@ -40,53 +39,40 @@ export const useCallingExpWithCallingStateEffect = () => {
4039
useEffect(() => {
4140
return () => {
4241
const callingx = getCallingxLibIfAvailable();
43-
if (!callingx) {
42+
if (!callingx || !activeCallCid) {
4443
return;
4544
}
46-
//as an alternative think about method which will return CallKit/Telecom state for given cid
47-
const incomingCallCid = RxUtils.getCurrentValue(
48-
voipPushNotificationCallCId$,
49-
);
50-
if (
51-
!activeCallCid ||
52-
!incomingCallCid ||
53-
incomingCallCid !== activeCallCid
54-
) {
45+
46+
const isCallRegistered = callingx.isCallRegistered(activeCallCid);
47+
if (!isCallRegistered) {
5548
logger.debug(
56-
`No active call cid to end in calling exp: ${activeCallCid} incomingCallCid: ${incomingCallCid}`,
49+
`No active call cid to end in calling exp: ${activeCallCid} isCallRegistered: ${isCallRegistered}`,
5750
);
5851
return;
5952
}
6053
//if incoming stream call was unmounted, we need to end the call in CallKit/Telecom
6154
//TODO: think about sending appropriate reason for end call
55+
logger.debug(`Ending call in calling exp: ${activeCallCid}`);
6256
callingx.endCallWithReason(activeCallCid, 'local');
63-
voipPushNotificationCallCId$.next(undefined);
6457
};
6558
}, [activeCallCid]);
6659

6760
useEffect(() => {
6861
const callingx = getCallingxLibIfAvailable();
69-
if (!callingx) {
62+
if (!callingx || !activeCallCid) {
7063
return;
7164
}
7265

73-
//as an alternative think about method which will return CallKit/Telecom state for given cid
74-
const incomingCallCid = RxUtils.getCurrentValue(
75-
voipPushNotificationCallCId$,
76-
);
77-
if (
78-
!incomingCallCid ||
79-
!activeCallCid ||
80-
incomingCallCid !== activeCallCid
81-
) {
66+
const isCallRegistered = callingx.isCallRegistered(activeCallCid);
67+
if (!isCallRegistered) {
8268
logger.debug(
83-
`No active call cid to end in calling exp: ${activeCallCid} incomingCallCid: ${incomingCallCid}`,
69+
`No active call cid to end in calling exp: ${activeCallCid} isCallRegistered: ${isCallRegistered}`,
8470
);
8571
return;
8672
}
8773

8874
logger.debug(
89-
`useEffect: ${activeCallCid} incomingCallCid: ${incomingCallCid}`,
75+
`useEffect: ${activeCallCid} isCallRegistered: ${isCallRegistered}`,
9076
);
9177
logger.debug(
9278
`prevState.current: ${prevState.current}, current callingState: ${callingState}`,
@@ -99,7 +85,7 @@ export const useCallingExpWithCallingStateEffect = () => {
9985
) {
10086
//in case call was registered as incoming and state changed to joined, we need to answer the call
10187
logger.debug(
102-
`Should accept call in callkeep: ${activeCallCid} callCid: ${incomingCallCid}`,
88+
`Should accept call in callkeep: ${activeCallCid} isCallRegistered: ${isCallRegistered}`,
10389
);
10490
callingx.answerIncomingCall(activeCallCid);
10591
} else if (
@@ -110,7 +96,6 @@ export const useCallingExpWithCallingStateEffect = () => {
11096
logger.debug(`Should end call in callkeep: ${activeCallCid}`);
11197
//TODO: think about sending appropriate reason for end call
11298
callingx.endCallWithReason(activeCallCid, 'local');
113-
voipPushNotificationCallCId$.next(undefined);
11499
}
115100
}
116101

@@ -119,21 +104,14 @@ export const useCallingExpWithCallingStateEffect = () => {
119104

120105
useEffect(() => {
121106
const callingx = getCallingxLibIfAvailable();
122-
if (!callingx) {
107+
if (!callingx || !activeCallCid) {
123108
return;
124109
}
125110

126-
//for now supports only incoming calls
127-
const incomingCallCid = RxUtils.getCurrentValue(
128-
voipPushNotificationCallCId$,
129-
);
130-
if (
131-
!incomingCallCid ||
132-
!activeCallCid ||
133-
incomingCallCid !== activeCallCid
134-
) {
111+
const isCallRegistered = callingx.isCallRegistered(activeCallCid);
112+
if (!isCallRegistered) {
135113
logger.debug(
136-
`No active call cid to set muted in calling exp: ${activeCallCid} incomingCallCid: ${incomingCallCid}`,
114+
`No active call cid to set muted in calling exp: ${activeCallCid} isCallRegistered: ${isCallRegistered}`,
137115
);
138116
return;
139117
}

packages/react-native-sdk/src/utils/push/android.ts

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import {
22
CallingState,
3-
RxUtils,
43
StreamVideoClient,
54
videoLoggerSystem,
65
} from '@stream-io/video-client';
@@ -18,10 +17,7 @@ import {
1817
getNotifeeLibThrowIfNotInstalledForPush,
1918
type NotifeeLib,
2019
} from './libs';
21-
import {
22-
pushNonRingingCallData$,
23-
voipPushNotificationCallCId$,
24-
} from './internal/rxSubjects';
20+
import { pushNonRingingCallData$ } from './internal/rxSubjects';
2521
import { pushUnsubscriptionCallbacks } from './internal/constants';
2622
import { canListenToWS, shouldCallBeClosed } from './internal/utils';
2723
import { setPushLogoutCallback } from '../internal/pushLogoutCallback';
@@ -151,14 +147,15 @@ export const firebaseDataHandler = async (
151147
return;
152148
}
153149

154-
if (RxUtils.getCurrentValue(voipPushNotificationCallCId$)) {
150+
const callingx = getCallingxLib();
151+
152+
if (callingx.isCallRegistered(call_cid)) {
155153
logger.debug(
156154
`call.ring notification already processed, skipping the call.ring notification`,
157155
);
158156
return;
159157
}
160158

161-
const callingx = getCallingxLib();
162159
await callingx.checkPermissions();
163160
if (!callingx.canPostNotifications()) {
164161
logger.debug(
@@ -190,7 +187,6 @@ export const firebaseDataHandler = async (
190187
logger.debug(
191188
`Displaying incoming call notification with callCid: ${call_cid} asForegroundService: ${asForegroundService}`,
192189
);
193-
voipPushNotificationCallCId$.next(call_cid);
194190

195191
if (asForegroundService) {
196192
// Listen to call events from WS through fg service
@@ -223,7 +219,6 @@ export const firebaseDataHandler = async (
223219
`Ending call with callCid: ${call_cid} shouldCallBeClosed`,
224220
'debug',
225221
);
226-
voipPushNotificationCallCId$.next(undefined);
227222
//TODO: think about sending appropriate reason for end call
228223
callingx.endCallWithReason(call_cid, 'remote');
229224
return;
@@ -251,7 +246,6 @@ export const firebaseDataHandler = async (
251246
);
252247
unsubscribeFunctions.forEach((fn) => fn());
253248

254-
voipPushNotificationCallCId$.next(undefined);
255249
finishBackgroundTask();
256250
//TODO: think about sending appropriate reason for end call
257251
callingx.endCallWithReason(call_cid, 'rejected');
@@ -275,7 +269,6 @@ export const firebaseDataHandler = async (
275269
`Ending call with callCid: ${call_cid} callingState: ${callingState}`,
276270
'debug',
277271
);
278-
voipPushNotificationCallCId$.next(undefined);
279272
finishBackgroundTask();
280273
callingx.endCallWithReason(call_cid, 'remote');
281274
}
@@ -297,7 +290,6 @@ export const firebaseDataHandler = async (
297290
`Ending call with callCid: ${call_cid} callId: ${callId}`,
298291
'debug',
299292
);
300-
voipPushNotificationCallCId$.next(undefined);
301293
finishBackgroundTask();
302294
callingx.endCallWithReason(callId, 'rejected');
303295
}

packages/react-native-sdk/src/utils/push/internal/ios.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
import { NativeModules, Platform } from 'react-native';
22
import { getVoipPushNotificationLib } from '../libs';
3-
import { voipPushNotificationCallCId$ } from './rxSubjects';
43
import { pushUnsubscriptionCallbacks } from './constants';
54
import { canListenToWS, shouldCallBeClosed } from './utils';
65
import { StreamVideoConfig } from '../../StreamVideoRN/types';
7-
import { RxUtils, videoLoggerSystem } from '@stream-io/video-client';
6+
import { videoLoggerSystem } from '@stream-io/video-client';
87
import { getCallingxLib } from '../libs/callingx';
98

109
export const onVoipNotificationReceived = async (
@@ -46,7 +45,8 @@ export const onVoipNotificationReceived = async (
4645
return;
4746
}
4847

49-
if (RxUtils.getCurrentValue(voipPushNotificationCallCId$)) {
48+
const callingx = getCallingxLib();
49+
if (callingx.isCallRegistered(call_cid)) {
5050
logger.debug(
5151
`call.ring notification already processed, skipping the call.ring notification`,
5252
);
@@ -74,7 +74,6 @@ export const onVoipNotificationReceived = async (
7474
if (mustEndCall) {
7575
logger.debug(`callkeep.reportEndCallWithUUID for call_cid: ${call_cid}`);
7676
//TODO: think about sending appropriate reason for end call
77-
const callingx = getCallingxLib();
7877
callingx.endCallWithReason(call_cid, 'remote');
7978

8079
const voipPushNotification = getVoipPushNotificationLib();
@@ -115,5 +114,4 @@ export const onVoipNotificationReceived = async (
115114
logger.debug(
116115
`call_cid:${call_cid} received and processed from call.ring push notification`,
117116
);
118-
voipPushNotificationCallCId$.next(call_cid);
119117
};

0 commit comments

Comments
 (0)