@100mslive/react-native-hms 1.12.2 → 2.0.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/android/build.gradle +70 -12
  2. package/android/src/main/java/com/reactnativehmssdk/HMSAudioshareActivity.kt +8 -8
  3. package/android/src/main/java/com/reactnativehmssdk/HMSHLSPlayer.kt +38 -12
  4. package/android/src/main/java/com/reactnativehmssdk/HMSHLSPlayerManagerImpl.kt +185 -0
  5. package/android/src/main/java/com/reactnativehmssdk/HMSHelper.kt +20 -10
  6. package/android/src/main/java/com/reactnativehmssdk/{HMSManager.kt → HMSManagerImpl.kt} +28 -111
  7. package/android/src/main/java/com/reactnativehmssdk/HMSRNSDK.kt +3 -3
  8. package/android/src/main/java/com/reactnativehmssdk/HMSReactNativeEvent.kt +29 -0
  9. package/android/src/main/java/com/reactnativehmssdk/HMSSDKViewManagerImpl.kt +119 -0
  10. package/android/src/main/java/com/reactnativehmssdk/HMSView.kt +33 -5
  11. package/android/src/main/java/com/reactnativehmssdk/HmsScreenshareActivity.kt +9 -9
  12. package/android/src/main/java/com/reactnativehmssdk/HmssdkPackage.kt +42 -3
  13. package/android/src/newarch/java/com/reactnativehmssdk/HMSHLSPlayerManager.kt +128 -0
  14. package/android/src/newarch/java/com/reactnativehmssdk/HMSManager.kt +332 -0
  15. package/android/src/newarch/java/com/reactnativehmssdk/HMSSDKViewManager.kt +102 -0
  16. package/android/src/oldarch/java/com/reactnativehmssdk/HMSHLSPlayerManager.kt +61 -0
  17. package/android/src/oldarch/java/com/reactnativehmssdk/HMSManager.kt +351 -0
  18. package/android/src/oldarch/java/com/reactnativehmssdk/HMSSDKViewManager.kt +87 -0
  19. package/ios/HMSHLSPlayerComponentView.mm +325 -0
  20. package/ios/HMSHLSPlayerManager.m +10 -0
  21. package/ios/HMSHLSPlayerManager.swift +91 -79
  22. package/ios/HMSManager.m +13 -0
  23. package/ios/HMSManager.mm +365 -0
  24. package/ios/HMSManager.swift +109 -103
  25. package/ios/HMSView.m +9 -0
  26. package/ios/HMSView.swift +44 -14
  27. package/ios/HMSViewComponentView.mm +229 -0
  28. package/lib/commonjs/classes/HmsView.js +45 -48
  29. package/lib/commonjs/classes/HmsView.js.map +1 -1
  30. package/lib/commonjs/components/HMSHLSPlayer/HMSHLSPlayer.js +46 -26
  31. package/lib/commonjs/components/HMSHLSPlayer/HMSHLSPlayer.js.map +1 -1
  32. package/lib/commonjs/components/HMSHLSPlayer/RCTHMSHLSPlayer.js +5 -4
  33. package/lib/commonjs/components/HMSHLSPlayer/RCTHMSHLSPlayer.js.map +1 -1
  34. package/lib/commonjs/modules/HMSManagerModule.js +3 -10
  35. package/lib/commonjs/modules/HMSManagerModule.js.map +1 -1
  36. package/lib/commonjs/specs/HMSHLSPlayerNativeComponent.js +75 -0
  37. package/lib/commonjs/specs/HMSHLSPlayerNativeComponent.js.map +1 -0
  38. package/lib/commonjs/specs/HMSViewNativeComponent.js +55 -0
  39. package/lib/commonjs/specs/HMSViewNativeComponent.js.map +1 -0
  40. package/lib/commonjs/specs/NativeHMSManager.js +38 -0
  41. package/lib/commonjs/specs/NativeHMSManager.js.map +1 -0
  42. package/lib/module/classes/HmsView.js +46 -49
  43. package/lib/module/classes/HmsView.js.map +1 -1
  44. package/lib/module/components/HMSHLSPlayer/HMSHLSPlayer.js +48 -28
  45. package/lib/module/components/HMSHLSPlayer/HMSHLSPlayer.js.map +1 -1
  46. package/lib/module/components/HMSHLSPlayer/RCTHMSHLSPlayer.js +3 -3
  47. package/lib/module/components/HMSHLSPlayer/RCTHMSHLSPlayer.js.map +1 -1
  48. package/lib/module/modules/HMSManagerModule.js +1 -9
  49. package/lib/module/modules/HMSManagerModule.js.map +1 -1
  50. package/lib/module/specs/HMSHLSPlayerNativeComponent.js +69 -0
  51. package/lib/module/specs/HMSHLSPlayerNativeComponent.js.map +1 -0
  52. package/lib/module/specs/HMSViewNativeComponent.js +49 -0
  53. package/lib/module/specs/HMSViewNativeComponent.js.map +1 -0
  54. package/lib/module/specs/NativeHMSManager.js +33 -0
  55. package/lib/module/specs/NativeHMSManager.js.map +1 -0
  56. package/lib/typescript/components/HMSHLSPlayer/RCTHMSHLSPlayer.d.ts +6 -9
  57. package/lib/typescript/specs/HMSHLSPlayerNativeComponent.d.ts +115 -0
  58. package/lib/typescript/specs/HMSViewNativeComponent.d.ts +97 -0
  59. package/lib/typescript/specs/NativeHMSManager.d.ts +147 -0
  60. package/package.json +16 -1
  61. package/react-native-hms.podspec +43 -0
  62. package/src/classes/HmsView.tsx +60 -78
  63. package/src/components/HMSHLSPlayer/HMSHLSPlayer.tsx +62 -128
  64. package/src/components/HMSHLSPlayer/RCTHMSHLSPlayer.ts +8 -13
  65. package/src/modules/HMSManagerModule.ts +1 -14
  66. package/src/specs/HMSHLSPlayerNativeComponent.ts +203 -0
  67. package/src/specs/HMSViewNativeComponent.ts +119 -0
  68. package/src/specs/NativeHMSManager.ts +307 -0
  69. package/android/src/main/java/com/reactnativehmssdk/HMSHLSPlayerManager.kt +0 -144
  70. package/android/src/main/java/com/reactnativehmssdk/HMSSDKViewManager.kt +0 -111
@@ -1,57 +1,21 @@
1
- import React, { useState, useImperativeHandle, useRef } from 'react';
2
- import {
3
- findNodeHandle,
4
- requireNativeComponent,
5
- StyleSheet,
6
- UIManager,
7
- Platform,
8
- } from 'react-native';
1
+ import React, {
2
+ useEffect,
3
+ useImperativeHandle,
4
+ useMemo,
5
+ useRef,
6
+ useState,
7
+ } from 'react';
8
+ import { StyleSheet, Platform } from 'react-native';
9
9
  import type { NativeSyntheticEvent, ViewStyle } from 'react-native';
10
+ import HmsView, { Commands } from '../specs/HMSViewNativeComponent';
10
11
  import { HMSConstants } from './HMSConstants';
11
12
  import { HMSVideoViewMode } from './HMSVideoViewMode';
12
13
  import { setHmsViewsResolutionsState } from '../hooks/hmsviews';
13
14
 
14
- /**
15
- * Interface defining the properties for the `HmsView` component.
16
- *
17
- * This interface specifies the structure of the props that the `HmsView` component expects. It includes
18
- * properties for configuring the video track display, such as the track ID, mirroring options,
19
- * and scale type. It also includes properties for handling events and customizing the component's style.
20
- *
21
- * @interface HmsViewProps
22
- * @property {Object} data - An object containing the track ID, instance ID, mirroring option, and scale type for the video or audio track.
23
- * @property {string} data.trackId - The unique identifier for the track to be displayed.
24
- * @property {string} data.id - The identifier for the `HmsViewComponent` instance.
25
- * @property {boolean} data.mirror - Indicates whether the video should be mirrored. This is commonly used for local video tracks.
26
- * @property {HMSVideoViewMode} data.scaleType - Determines how the video fits within the bounds of the view (e.g., aspect fill, aspect fit).
27
- * @property {boolean} autoSimulcast - Enables automatic simulcast layer switching based on network conditions, if supported.
28
- * @property {boolean} setZOrderMediaOverlay - When true, the video view will be rendered above the regular view hierarchy.
29
- * @property {ViewStyle} style - Custom styles to apply to the view.
30
- * @property {Function} onChange - A callback function that is invoked when the `HmsView` component emits a change event.
31
- * @property {Function} onDataReturned - A callback function that is invoked when the `HmsView` component returns data in response to a capture frame event.
32
- *
33
- * @see {https://www.100ms.live/docs/react-native/v2/how-to-guides/set-up-video-conferencing/render-video/overview}
34
- */
35
- interface HmsViewProps {
36
- data: {
37
- trackId: string;
38
- id: string;
39
- mirror: boolean;
40
- scaleType: HMSVideoViewMode;
41
- };
42
- autoSimulcast: boolean;
43
- setZOrderMediaOverlay: boolean;
44
- scaleType: HMSVideoViewMode;
45
- style: ViewStyle;
46
- onChange: Function;
47
- onDataReturned: Function;
48
- }
49
-
50
- // Imports the `HmsView` component from the native side using the `requireNativeComponent` function.
51
- // This component is used to render video tracks in the application.
52
- const HmsView = requireNativeComponent<HmsViewProps>('HMSView');
53
- let _nextRequestId = 1;
54
- let _requestMap = new Map();
15
+ type CapturePromiseMethods = {
16
+ resolve: (value: unknown) => void;
17
+ reject: (reason?: unknown) => void;
18
+ };
55
19
 
56
20
  /**
57
21
  * Defines the properties for the `HmsViewComponent`.
@@ -93,12 +57,25 @@ export const HmsViewComponent = React.forwardRef<any, HmsComponentProps>(
93
57
 
94
58
  const hmsViewRef: any = useRef();
95
59
  const [applyStyles_ANDROID, setApplyStyles_ANDROID] = useState(false);
96
- const data = {
97
- trackId,
98
- id,
99
- mirror,
100
- scaleType,
101
- };
60
+ // Memoized so the object reference is stable across renders unless one
61
+ // of the inputs actually changes. Fabric diffs view props by reference
62
+ // before doing a deep compare — a fresh `{...}` on every render would
63
+ // trigger redundant native prop updates.
64
+ const data = useMemo(
65
+ () => ({ trackId, id, mirror, scaleType }),
66
+ [trackId, id, mirror, scaleType]
67
+ );
68
+
69
+ // Per-instance request/response state for the `capture` imperative.
70
+ // Each `<HmsView />` gets its own counter + pending-promise map so:
71
+ // - requestIds can't collide across multiple HmsView instances
72
+ // - pending promises are scoped to this view and cleaned up when
73
+ // it unmounts (see the useEffect below)
74
+ const nextRequestId = useRef(1);
75
+ const requestMap = useMemo(
76
+ () => new Map<number, CapturePromiseMethods>(),
77
+ []
78
+ );
102
79
 
103
80
  /**
104
81
  * This method is passed to `onChange` prop of `HmsView` Native Component.
@@ -126,38 +103,30 @@ export const HmsViewComponent = React.forwardRef<any, HmsComponentProps>(
126
103
  const _onDataReturned = (event: {
127
104
  nativeEvent: { requestId: any; result: any; error: any };
128
105
  }) => {
129
- // We grab the relevant data out of our event.
130
- let { requestId, result, error } = event.nativeEvent;
131
- // Then we get the promise we saved earlier for the given request ID.
132
- let promise = _requestMap.get(requestId);
106
+ const { requestId, result, error } = event.nativeEvent;
107
+ const promise = requestMap.get(requestId);
108
+ if (!promise) {
109
+ // No pending request — typically a late event after unmount/cleanup
110
+ // rejected it, or a stale requestId from a previous mount.
111
+ return;
112
+ }
133
113
  if (result) {
134
- // If it was successful, we resolve the promise.
135
114
  promise.resolve(result);
136
115
  } else {
137
- // Otherwise, we reject it.
138
116
  promise.reject(error);
139
117
  }
140
- // Finally, we clean up our request map.
141
- _requestMap.delete(requestId);
118
+ requestMap.delete(requestId);
142
119
  };
143
120
 
144
121
  const capture = async () => {
145
- const viewManagerConfig = UIManager.getViewManagerConfig('HMSView');
146
-
147
- let requestId = _nextRequestId++;
148
- let requestMap = _requestMap;
149
-
150
- // We create a promise here that will be resolved once `_onRequestDone` is
151
- // called.
152
- let promise = new Promise(function (resolve, reject) {
122
+ const requestId = nextRequestId.current++;
123
+ const promise = new Promise((resolve, reject) => {
153
124
  requestMap.set(requestId, { resolve, reject });
154
125
  });
155
126
 
156
- UIManager.dispatchViewManagerCommand(
157
- findNodeHandle(hmsViewRef.current),
158
- viewManagerConfig.Commands.capture,
159
- [requestId]
160
- );
127
+ if (hmsViewRef.current) {
128
+ Commands.capture(hmsViewRef.current, requestId);
129
+ }
161
130
  return promise;
162
131
  };
163
132
 
@@ -167,10 +136,23 @@ export const HmsViewComponent = React.forwardRef<any, HmsComponentProps>(
167
136
  };
168
137
  });
169
138
 
139
+ // Reject any in-flight capture promises on unmount. Under bridgeless
140
+ // mode the native side may not be able to deliver the captureFrame
141
+ // event back (event dispatcher returns null when the React tag is
142
+ // gone), which would leave promises hanging in the map forever.
143
+ useEffect(() => {
144
+ return () => {
145
+ requestMap.forEach(({ reject }) => {
146
+ reject(new Error('HmsView unmounted before capture completed'));
147
+ });
148
+ requestMap.clear();
149
+ };
150
+ }, [requestMap]);
151
+
170
152
  return (
171
153
  <HmsView
172
154
  ref={hmsViewRef}
173
- onChange={onChange}
155
+ onResolutionChange={onChange as any}
174
156
  data={data}
175
157
  style={
176
158
  Platform.OS === 'android' ? (applyStyles_ANDROID ? style : {}) : style
@@ -178,7 +160,7 @@ export const HmsViewComponent = React.forwardRef<any, HmsComponentProps>(
178
160
  autoSimulcast={autoSimulcast}
179
161
  scaleType={scaleType}
180
162
  setZOrderMediaOverlay={setZOrderMediaOverlay}
181
- onDataReturned={_onDataReturned}
163
+ onDataReturned={_onDataReturned as any}
182
164
  />
183
165
  );
184
166
  }
@@ -1,11 +1,5 @@
1
1
  import React, { useEffect, useImperativeHandle, useMemo, useRef } from 'react';
2
- import {
3
- View,
4
- StyleSheet,
5
- UIManager,
6
- findNodeHandle,
7
- Platform,
8
- } from 'react-native';
2
+ import { View, StyleSheet, Platform } from 'react-native';
9
3
  import type { StyleProp, ViewStyle } from 'react-native';
10
4
 
11
5
  import {
@@ -17,10 +11,7 @@ import {
17
11
  setHMSHLSPlayerStatsError,
18
12
  setHMSHLSPlayerSubtitles,
19
13
  } from './hooks';
20
- import {
21
- RCTHMSHLSPlayer,
22
- RCTHMSHLSPlayerViewManagerConfig,
23
- } from './RCTHMSHLSPlayer';
14
+ import { RCTHMSHLSPlayer, RCTHMSHLSPlayerCommands } from './RCTHMSHLSPlayer';
24
15
  import type {
25
16
  HlsSPlayerCuesEventHandler,
26
17
  HmsHlsPlaybackEventHandler,
@@ -87,52 +78,30 @@ const _HMSHLSPlayer: React.ForwardRefRenderFunction<
87
78
  useImperativeHandle(
88
79
  ref,
89
80
  () => ({
81
+ // `url` is optional at the JS API level: omit it (or pass undefined)
82
+ // to play the URL currently configured on the player; pass a string
83
+ // to switch to a new stream. The Codegen `play` command signature is
84
+ // `(viewRef, url: string)` (non-optional), so we pass `''` to mean
85
+ // "no override" — the native side treats empty-string as the
86
+ // "use existing url" sentinel.
90
87
  play: (url?: string) => {
91
- if (
92
- hmsHlsPlayerRef.current &&
93
- RCTHMSHLSPlayerViewManagerConfig.Commands.play
94
- ) {
95
- UIManager.dispatchViewManagerCommand(
96
- findNodeHandle(hmsHlsPlayerRef.current),
97
- RCTHMSHLSPlayerViewManagerConfig.Commands.play,
98
- url ? [url] : ['']
99
- );
88
+ if (hmsHlsPlayerRef.current) {
89
+ RCTHMSHLSPlayerCommands.play(hmsHlsPlayerRef.current, url ?? '');
100
90
  }
101
91
  },
102
92
  stop: () => {
103
- if (
104
- hmsHlsPlayerRef.current &&
105
- RCTHMSHLSPlayerViewManagerConfig.Commands.stop
106
- ) {
107
- UIManager.dispatchViewManagerCommand(
108
- findNodeHandle(hmsHlsPlayerRef.current),
109
- RCTHMSHLSPlayerViewManagerConfig.Commands.stop,
110
- undefined
111
- );
93
+ if (hmsHlsPlayerRef.current) {
94
+ RCTHMSHLSPlayerCommands.stop(hmsHlsPlayerRef.current);
112
95
  }
113
96
  },
114
97
  pause: () => {
115
- if (
116
- hmsHlsPlayerRef.current &&
117
- RCTHMSHLSPlayerViewManagerConfig.Commands.pause
118
- ) {
119
- UIManager.dispatchViewManagerCommand(
120
- findNodeHandle(hmsHlsPlayerRef.current),
121
- RCTHMSHLSPlayerViewManagerConfig.Commands.pause,
122
- undefined
123
- );
98
+ if (hmsHlsPlayerRef.current) {
99
+ RCTHMSHLSPlayerCommands.pause(hmsHlsPlayerRef.current);
124
100
  }
125
101
  },
126
102
  resume: () => {
127
- if (
128
- hmsHlsPlayerRef.current &&
129
- RCTHMSHLSPlayerViewManagerConfig.Commands.resume
130
- ) {
131
- UIManager.dispatchViewManagerCommand(
132
- findNodeHandle(hmsHlsPlayerRef.current),
133
- RCTHMSHLSPlayerViewManagerConfig.Commands.resume,
134
- undefined
135
- );
103
+ if (hmsHlsPlayerRef.current) {
104
+ RCTHMSHLSPlayerCommands.resume(hmsHlsPlayerRef.current);
136
105
  }
137
106
  },
138
107
  seekForward: (seconds: number) => {
@@ -144,15 +113,8 @@ const _HMSHLSPlayer: React.ForwardRefRenderFunction<
144
113
  );
145
114
  }
146
115
 
147
- if (
148
- hmsHlsPlayerRef.current &&
149
- RCTHMSHLSPlayerViewManagerConfig.Commands.seekForward
150
- ) {
151
- UIManager.dispatchViewManagerCommand(
152
- findNodeHandle(hmsHlsPlayerRef.current),
153
- RCTHMSHLSPlayerViewManagerConfig.Commands.seekForward,
154
- [seconds]
155
- );
116
+ if (hmsHlsPlayerRef.current) {
117
+ RCTHMSHLSPlayerCommands.seekForward(hmsHlsPlayerRef.current, seconds);
156
118
  }
157
119
  },
158
120
  seekBackward: (seconds: number) => {
@@ -164,27 +126,16 @@ const _HMSHLSPlayer: React.ForwardRefRenderFunction<
164
126
  );
165
127
  }
166
128
 
167
- if (
168
- hmsHlsPlayerRef.current &&
169
- RCTHMSHLSPlayerViewManagerConfig.Commands.seekBackward
170
- ) {
171
- UIManager.dispatchViewManagerCommand(
172
- findNodeHandle(hmsHlsPlayerRef.current),
173
- RCTHMSHLSPlayerViewManagerConfig.Commands.seekBackward,
174
- [seconds]
129
+ if (hmsHlsPlayerRef.current) {
130
+ RCTHMSHLSPlayerCommands.seekBackward(
131
+ hmsHlsPlayerRef.current,
132
+ seconds
175
133
  );
176
134
  }
177
135
  },
178
136
  seekToLivePosition: () => {
179
- if (
180
- hmsHlsPlayerRef.current &&
181
- RCTHMSHLSPlayerViewManagerConfig.Commands.seekToLivePosition
182
- ) {
183
- UIManager.dispatchViewManagerCommand(
184
- findNodeHandle(hmsHlsPlayerRef.current),
185
- RCTHMSHLSPlayerViewManagerConfig.Commands.seekToLivePosition,
186
- undefined
187
- );
137
+ if (hmsHlsPlayerRef.current) {
138
+ RCTHMSHLSPlayerCommands.seekToLivePosition(hmsHlsPlayerRef.current);
188
139
  }
189
140
  },
190
141
  setVolume: (level: number) => {
@@ -194,84 +145,52 @@ const _HMSHLSPlayer: React.ForwardRefRenderFunction<
194
145
  );
195
146
  }
196
147
 
197
- if (
198
- hmsHlsPlayerRef.current &&
199
- RCTHMSHLSPlayerViewManagerConfig.Commands.setVolume
200
- ) {
201
- UIManager.dispatchViewManagerCommand(
202
- findNodeHandle(hmsHlsPlayerRef.current),
203
- RCTHMSHLSPlayerViewManagerConfig.Commands.setVolume,
204
- [level]
205
- );
148
+ if (hmsHlsPlayerRef.current) {
149
+ RCTHMSHLSPlayerCommands.setVolume(hmsHlsPlayerRef.current, level);
206
150
  }
207
151
  },
208
152
  isClosedCaptionSupported: () => {
209
- if (
210
- hmsHlsPlayerRef.current &&
211
- RCTHMSHLSPlayerViewManagerConfig.Commands.areClosedCaptionSupported
212
- ) {
153
+ if (hmsHlsPlayerRef.current) {
213
154
  const requestId = currentRequestId.current++;
214
155
  const promise = new Promise<boolean>((resolve, reject) => {
215
156
  promiseAndIdsMap.set(requestId, { resolve, reject });
216
157
  });
217
158
 
218
- UIManager.dispatchViewManagerCommand(
219
- findNodeHandle(hmsHlsPlayerRef.current),
220
- RCTHMSHLSPlayerViewManagerConfig.Commands.areClosedCaptionSupported,
221
- [requestId]
159
+ RCTHMSHLSPlayerCommands.areClosedCaptionSupported(
160
+ hmsHlsPlayerRef.current,
161
+ requestId
222
162
  );
223
163
  return promise;
224
164
  }
225
165
  return Promise.resolve(false);
226
166
  },
227
167
  isClosedCaptionEnabled: () => {
228
- if (
229
- hmsHlsPlayerRef.current &&
230
- RCTHMSHLSPlayerViewManagerConfig.Commands.isClosedCaptionEnabled
231
- ) {
168
+ if (hmsHlsPlayerRef.current) {
232
169
  const requestId = currentRequestId.current++;
233
170
  const promise = new Promise<boolean>((resolve, reject) => {
234
171
  promiseAndIdsMap.set(requestId, { resolve, reject });
235
172
  });
236
173
 
237
- UIManager.dispatchViewManagerCommand(
238
- findNodeHandle(hmsHlsPlayerRef.current),
239
- RCTHMSHLSPlayerViewManagerConfig.Commands.isClosedCaptionEnabled,
240
- [requestId]
174
+ RCTHMSHLSPlayerCommands.isClosedCaptionEnabled(
175
+ hmsHlsPlayerRef.current,
176
+ requestId
241
177
  );
242
178
  return promise;
243
179
  }
244
180
  return Promise.resolve(false);
245
181
  },
246
182
  enableClosedCaption: () => {
247
- if (
248
- hmsHlsPlayerRef.current &&
249
- RCTHMSHLSPlayerViewManagerConfig.Commands.enableClosedCaption
250
- ) {
251
- UIManager.dispatchViewManagerCommand(
252
- findNodeHandle(hmsHlsPlayerRef.current),
253
- RCTHMSHLSPlayerViewManagerConfig.Commands.enableClosedCaption,
254
- undefined
255
- );
183
+ if (hmsHlsPlayerRef.current) {
184
+ RCTHMSHLSPlayerCommands.enableClosedCaption(hmsHlsPlayerRef.current);
256
185
  }
257
186
  },
258
187
  disableClosedCaption: () => {
259
- if (
260
- hmsHlsPlayerRef.current &&
261
- RCTHMSHLSPlayerViewManagerConfig.Commands.disableClosedCaption
262
- ) {
263
- UIManager.dispatchViewManagerCommand(
264
- findNodeHandle(hmsHlsPlayerRef.current),
265
- RCTHMSHLSPlayerViewManagerConfig.Commands.disableClosedCaption,
266
- undefined
267
- );
188
+ if (hmsHlsPlayerRef.current) {
189
+ RCTHMSHLSPlayerCommands.disableClosedCaption(hmsHlsPlayerRef.current);
268
190
  }
269
191
  },
270
192
  getPlayerDurationDetails: () => {
271
- if (
272
- hmsHlsPlayerRef.current &&
273
- RCTHMSHLSPlayerViewManagerConfig.Commands.getPlayerDurationDetails
274
- ) {
193
+ if (hmsHlsPlayerRef.current) {
275
194
  const requestId = currentRequestId.current++;
276
195
  const promise = new Promise<HLSPlayerDurationDetails>(
277
196
  (resolve, reject) => {
@@ -279,10 +198,9 @@ const _HMSHLSPlayer: React.ForwardRefRenderFunction<
279
198
  }
280
199
  );
281
200
 
282
- UIManager.dispatchViewManagerCommand(
283
- findNodeHandle(hmsHlsPlayerRef.current),
284
- RCTHMSHLSPlayerViewManagerConfig.Commands.getPlayerDurationDetails,
285
- [requestId]
201
+ RCTHMSHLSPlayerCommands.getPlayerDurationDetails(
202
+ hmsHlsPlayerRef.current,
203
+ requestId
286
204
  );
287
205
  return promise;
288
206
  }
@@ -359,13 +277,27 @@ const _HMSHLSPlayer: React.ForwardRefRenderFunction<
359
277
  return;
360
278
  }
361
279
  promiseMethods.resolve(data);
280
+ // Remove the entry so the map doesn't grow unboundedly across the
281
+ // lifetime of the player view.
282
+ promiseAndIdsMap.delete(requestId);
362
283
  };
363
284
 
364
285
  useEffect(() => {
365
286
  return () => {
366
287
  useHMSStore.getState().resetPlaybackSlice();
367
288
  useHMSHLSPlayerStatsStore.getState().reset();
289
+ // Reject any in-flight command promises that didn't get a response
290
+ // before unmount. Under bridgeless mode the native side may not be
291
+ // able to deliver `onDataReturned` events back if the React tag is
292
+ // gone — left unrejected, those promises would hang forever.
293
+ promiseAndIdsMap.forEach(({ reject }) => {
294
+ reject(
295
+ new Error('HMSHLSPlayer unmounted before command response arrived')
296
+ );
297
+ });
298
+ promiseAndIdsMap.clear();
368
299
  };
300
+ // eslint-disable-next-line react-hooks/exhaustive-deps
369
301
  }, []);
370
302
 
371
303
  return (
@@ -377,12 +309,14 @@ const _HMSHLSPlayer: React.ForwardRefRenderFunction<
377
309
  style={styles.player}
378
310
  enableStats={enableStats}
379
311
  enableControls={enableControls}
380
- onHmsHlsPlaybackEvent={handleHLSPlaybackEvent}
381
- onHmsHlsStatsEvent={handleHLSStatsEvent}
312
+ onHmsHlsPlaybackEvent={handleHLSPlaybackEvent as any}
313
+ onHmsHlsStatsEvent={handleHLSStatsEvent as any}
382
314
  onHlsPlayerCuesEvent={
383
- Platform.OS === 'android' ? handleHLSPlayerCuesEvent : undefined
315
+ Platform.OS === 'android'
316
+ ? (handleHLSPlayerCuesEvent as any)
317
+ : undefined
384
318
  }
385
- onDataReturned={handleRequestedDataReturned}
319
+ onDataReturned={handleRequestedDataReturned as any}
386
320
  />
387
321
  </View>
388
322
  </View>
@@ -1,10 +1,8 @@
1
- import { requireNativeComponent, UIManager } from 'react-native';
2
- import type {
3
- StyleProp,
4
- NativeSyntheticEvent,
5
- ViewStyle,
6
- NativeMethods,
7
- } from 'react-native';
1
+ import type { ElementRef } from 'react';
2
+ import type { StyleProp, NativeSyntheticEvent, ViewStyle } from 'react-native';
3
+ import HMSHLSPlayerNativeComponent, {
4
+ Commands,
5
+ } from '../../specs/HMSHLSPlayerNativeComponent';
8
6
  import type {
9
7
  HMSHLSPlayerCuesEvent,
10
8
  HMSHLSPlayerPlaybackEvent,
@@ -39,11 +37,8 @@ export type RCTHMSHLSPlayerProps = {
39
37
  onHlsPlayerCuesEvent?: HlsSPlayerCuesEventHandler;
40
38
  };
41
39
 
42
- export const RCTHMSHLSPlayer =
43
- requireNativeComponent<RCTHMSHLSPlayerProps>('HMSHLSPlayer');
40
+ export const RCTHMSHLSPlayer = HMSHLSPlayerNativeComponent;
44
41
 
45
- export type RCTHMSHLSPlayerRef = React.Component<RCTHMSHLSPlayerProps> &
46
- Readonly<NativeMethods>;
42
+ export const RCTHMSHLSPlayerCommands = Commands;
47
43
 
48
- export const RCTHMSHLSPlayerViewManagerConfig =
49
- UIManager.getViewManagerConfig('HMSHLSPlayer');
44
+ export type RCTHMSHLSPlayerRef = ElementRef<typeof RCTHMSHLSPlayer>;
@@ -1,17 +1,4 @@
1
- import { NativeModules } from 'react-native';
2
-
3
- const { HMSManager } = NativeModules;
4
-
5
- if (HMSManager == null) {
6
- console.error(
7
- `[@100mslive/react-native-hms] react-native-hms module was not found. Make sure you're running your app on the native platform and your code is linked properly (cd ios && pod install && cd ..).
8
-
9
- For installation instructions, please refer to https://www.100ms.live/docs/react-native/v2/how-to-guides/install-the-sdk/integration`
10
- .split('\n')
11
- .map((line) => line.trim())
12
- .join('\n')
13
- );
14
- }
1
+ import HMSManager from '../specs/NativeHMSManager';
15
2
 
16
3
  export type HMSManagerProps = any;
17
4