Skip to content

Commit e05e3bf

Browse files
committed
feat: implement video conference action listener and event emission
- Added a listener for video conference actions from the native side to handle Accept/Decline actions when the app is in the background. - Enhanced the VideoConfModule to emit events to JavaScript when a video conference action is stored. - Updated the Root component to set up and clean up the video conference action listener.
1 parent 81166aa commit e05e3bf

File tree

3 files changed

+69
-3
lines changed

3 files changed

+69
-3
lines changed

android/app/src/main/java/chat/rocket/reactnative/notification/VideoConfModule.kt

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import android.content.Context
44
import com.facebook.react.bridge.Promise
55
import com.facebook.react.bridge.ReactApplicationContext
66
import com.facebook.react.bridge.ReactMethod
7+
import com.facebook.react.modules.core.DeviceEventManagerModule
8+
import java.lang.ref.WeakReference
79

810
/**
911
* Native module to expose video conference notification actions to JavaScript.
@@ -14,9 +16,20 @@ class VideoConfModule(reactContext: ReactApplicationContext) : NativeVideoConfSp
1416
companion object {
1517
private const val PREFS_NAME = "RocketChatPrefs"
1618
private const val KEY_VIDEO_CONF_ACTION = "videoConfAction"
19+
private const val EVENT_VIDEO_CONF_ACTION = "VideoConfAction"
20+
21+
private var reactContextRef: WeakReference<ReactApplicationContext>? = null
1722

1823
/**
19-
* Stores a video conference action.
24+
* Sets the React context reference for event emission.
25+
*/
26+
@JvmStatic
27+
fun setReactContext(context: ReactApplicationContext) {
28+
reactContextRef = WeakReference(context)
29+
}
30+
31+
/**
32+
* Stores a video conference action and emits event to JS if app is running.
2033
* Called from native code when user interacts with video conf notification.
2134
*/
2235
@JvmStatic
@@ -25,7 +38,32 @@ class VideoConfModule(reactContext: ReactApplicationContext) : NativeVideoConfSp
2538
.edit()
2639
.putString(KEY_VIDEO_CONF_ACTION, actionJson)
2740
.apply()
41+
42+
// Emit event to JS if React context is available (app is running)
43+
emitVideoConfActionEvent(actionJson)
2844
}
45+
46+
/**
47+
* Emits a video conf action event to JavaScript.
48+
*/
49+
private fun emitVideoConfActionEvent(actionJson: String) {
50+
try {
51+
reactContextRef?.get()?.let { context ->
52+
if (context.hasActiveReactInstance()) {
53+
context
54+
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
55+
.emit(EVENT_VIDEO_CONF_ACTION, actionJson)
56+
}
57+
}
58+
} catch (e: Exception) {
59+
// Ignore - React context not available
60+
}
61+
}
62+
}
63+
64+
init {
65+
// Store reference for event emission
66+
setReactContext(reactApplicationContext)
2967
}
3068

3169
/**

app/index.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ import {
3232
unsubscribeTheme
3333
} from './lib/methods/helpers/theme';
3434
import { initializePushNotifications, onNotification } from './lib/notifications';
35-
import { getInitialNotification } from './lib/notifications/videoConf/getInitialNotification';
35+
import { getInitialNotification, setupVideoConfActionListener } from './lib/notifications/videoConf/getInitialNotification';
3636
import store from './lib/store';
3737
import { initStore } from './lib/store/auxStore';
3838
import { type TSupportedThemes, ThemeContext } from './theme';
@@ -85,6 +85,7 @@ const parseDeepLinking = (url: string) => {
8585
export default class Root extends React.Component<{}, IState> {
8686
private listenerTimeout!: any;
8787
private dimensionsListener?: EmitterSubscription;
88+
private videoConfActionCleanup?: () => void;
8889

8990
constructor(props: any) {
9091
super(props);
@@ -116,11 +117,15 @@ export default class Root extends React.Component<{}, IState> {
116117
});
117118
}, 5000);
118119
this.dimensionsListener = Dimensions.addEventListener('change', this.onDimensionsChange);
120+
121+
// Set up video conf action listener for background accept/decline
122+
this.videoConfActionCleanup = setupVideoConfActionListener();
119123
}
120124

121125
componentWillUnmount() {
122126
clearTimeout(this.listenerTimeout);
123127
this.dimensionsListener?.remove?.();
128+
this.videoConfActionCleanup?.();
124129

125130
unsubscribeTheme();
126131
}

app/lib/notifications/videoConf/getInitialNotification.ts

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,34 @@
11
import * as Notifications from 'expo-notifications';
22
import EJSON from 'ejson';
3-
import { Platform } from 'react-native';
3+
import { DeviceEventEmitter, Platform } from 'react-native';
44

55
import { deepLinkingClickCallPush } from '../../../actions/deepLinking';
66
import { store } from '../../store/auxStore';
77
import NativeVideoConfModule from '../../native/NativeVideoConfAndroid';
88

9+
/**
10+
* Sets up listener for video conference actions from native side.
11+
* This handles the case when app is in background and user taps Accept/Decline.
12+
*/
13+
export const setupVideoConfActionListener = (): (() => void) | undefined => {
14+
if (Platform.OS === 'android') {
15+
const subscription = DeviceEventEmitter.addListener('VideoConfAction', (actionJson: string) => {
16+
try {
17+
const data = JSON.parse(actionJson);
18+
if (data?.notificationType === 'videoconf') {
19+
store.dispatch(deepLinkingClickCallPush(data));
20+
}
21+
} catch (error) {
22+
console.log('Error handling video conf action event:', error);
23+
}
24+
});
25+
26+
// Return cleanup function
27+
return () => subscription.remove();
28+
}
29+
return undefined;
30+
};
31+
932
/**
1033
* Check for pending video conference actions from native notification handling.
1134
* @returns true if a video conf action was found and dispatched, false otherwise

0 commit comments

Comments
 (0)