@stream-io/video-react-native-sdk 1.30.4 → 1.31.0

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 (50) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/android/src/main/java/com/streamvideo/reactnative/StreamVideoReactNativeModule.kt +85 -0
  3. package/android/src/main/java/com/streamvideo/reactnative/screenshare/ScreenAudioCapture.kt +111 -0
  4. package/dist/commonjs/components/Call/CallControls/ScreenShareToggleButton.js +3 -2
  5. package/dist/commonjs/components/Call/CallControls/ScreenShareToggleButton.js.map +1 -1
  6. package/dist/commonjs/hooks/index.js +11 -0
  7. package/dist/commonjs/hooks/index.js.map +1 -1
  8. package/dist/commonjs/hooks/useScreenShareAudioMixing.js +126 -0
  9. package/dist/commonjs/hooks/useScreenShareAudioMixing.js.map +1 -0
  10. package/dist/commonjs/hooks/useScreenShareButton.js +57 -3
  11. package/dist/commonjs/hooks/useScreenShareButton.js.map +1 -1
  12. package/dist/commonjs/modules/ScreenShareAudioManager.js +54 -0
  13. package/dist/commonjs/modules/ScreenShareAudioManager.js.map +1 -0
  14. package/dist/commonjs/providers/StreamCall/index.js +11 -1
  15. package/dist/commonjs/providers/StreamCall/index.js.map +1 -1
  16. package/dist/commonjs/version.js +1 -1
  17. package/dist/module/components/Call/CallControls/ScreenShareToggleButton.js +3 -2
  18. package/dist/module/components/Call/CallControls/ScreenShareToggleButton.js.map +1 -1
  19. package/dist/module/hooks/index.js +1 -0
  20. package/dist/module/hooks/index.js.map +1 -1
  21. package/dist/module/hooks/useScreenShareAudioMixing.js +119 -0
  22. package/dist/module/hooks/useScreenShareAudioMixing.js.map +1 -0
  23. package/dist/module/hooks/useScreenShareButton.js +57 -3
  24. package/dist/module/hooks/useScreenShareButton.js.map +1 -1
  25. package/dist/module/modules/ScreenShareAudioManager.js +47 -0
  26. package/dist/module/modules/ScreenShareAudioManager.js.map +1 -0
  27. package/dist/module/providers/StreamCall/index.js +11 -1
  28. package/dist/module/providers/StreamCall/index.js.map +1 -1
  29. package/dist/module/version.js +1 -1
  30. package/dist/typescript/components/Call/CallControls/ScreenShareToggleButton.d.ts +6 -1
  31. package/dist/typescript/components/Call/CallControls/ScreenShareToggleButton.d.ts.map +1 -1
  32. package/dist/typescript/hooks/index.d.ts +1 -0
  33. package/dist/typescript/hooks/index.d.ts.map +1 -1
  34. package/dist/typescript/hooks/useScreenShareAudioMixing.d.ts +14 -0
  35. package/dist/typescript/hooks/useScreenShareAudioMixing.d.ts.map +1 -0
  36. package/dist/typescript/hooks/useScreenShareButton.d.ts +39 -2
  37. package/dist/typescript/hooks/useScreenShareButton.d.ts.map +1 -1
  38. package/dist/typescript/modules/ScreenShareAudioManager.d.ts +28 -0
  39. package/dist/typescript/modules/ScreenShareAudioManager.d.ts.map +1 -0
  40. package/dist/typescript/providers/StreamCall/index.d.ts.map +1 -1
  41. package/dist/typescript/version.d.ts +1 -1
  42. package/ios/StreamVideoReactNative.m +93 -4
  43. package/package.json +7 -7
  44. package/src/components/Call/CallControls/ScreenShareToggleButton.tsx +11 -1
  45. package/src/hooks/index.ts +1 -0
  46. package/src/hooks/useScreenShareAudioMixing.ts +130 -0
  47. package/src/hooks/useScreenShareButton.ts +87 -2
  48. package/src/modules/ScreenShareAudioManager.ts +49 -0
  49. package/src/providers/StreamCall/index.tsx +11 -0
  50. package/src/version.ts +1 -1
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.screenShareAudioMixingManager = exports.ScreenShareAudioManager = void 0;
7
+ var _reactNative = require("react-native");
8
+ const StreamVideoReactNative = _reactNative.NativeModules.StreamVideoReactNative;
9
+ class ScreenShareAudioManager {
10
+ /**
11
+ * Starts mixing screen share audio into the microphone audio track.
12
+ * On iOS, this enables audio buffer processing on the prepared mixer.
13
+ * On Android, this registers an audio processor that captures system media
14
+ * audio via AudioPlaybackCaptureConfiguration and mixes it into the mic buffer.
15
+ */
16
+ async startScreenShareAudioMixing() {
17
+ return StreamVideoReactNative?.startScreenShareAudioMixing();
18
+ }
19
+
20
+ /**
21
+ * Stops mixing screen share audio into the microphone audio track
22
+ * and restores the original audio pipeline.
23
+ */
24
+ async stopScreenShareAudioMixing() {
25
+ return StreamVideoReactNative?.stopScreenShareAudioMixing();
26
+ }
27
+
28
+ /**
29
+ * Starts in-app screen capture using RPScreenRecorder (iOS only).
30
+ * Unlike broadcast screen sharing, in-app capture runs in the main app process
31
+ * and can directly provide `.audioApp` sample buffers for mixing.
32
+ *
33
+ * @param includeAudio Whether to capture and mix app audio.
34
+ */
35
+ async startInAppScreenCapture(includeAudio) {
36
+ if (_reactNative.Platform.OS !== 'ios') {
37
+ return;
38
+ }
39
+ return StreamVideoReactNative?.startInAppScreenCapture(includeAudio);
40
+ }
41
+
42
+ /**
43
+ * Stops in-app screen capture (iOS only).
44
+ */
45
+ async stopInAppScreenCapture() {
46
+ if (_reactNative.Platform.OS !== 'ios') {
47
+ return;
48
+ }
49
+ return StreamVideoReactNative?.stopInAppScreenCapture();
50
+ }
51
+ }
52
+ exports.ScreenShareAudioManager = ScreenShareAudioManager;
53
+ const screenShareAudioMixingManager = exports.screenShareAudioMixingManager = new ScreenShareAudioManager();
54
+ //# sourceMappingURL=ScreenShareAudioManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_reactNative","require","StreamVideoReactNative","NativeModules","ScreenShareAudioManager","startScreenShareAudioMixing","stopScreenShareAudioMixing","startInAppScreenCapture","includeAudio","Platform","OS","stopInAppScreenCapture","exports","screenShareAudioMixingManager"],"sourceRoot":"../../../src","sources":["modules/ScreenShareAudioManager.ts"],"mappings":";;;;;;AAAA,IAAAA,YAAA,GAAAC,OAAA;AAEA,MAAMC,sBAAsB,GAAGC,0BAAa,CAACD,sBAAsB;AAE5D,MAAME,uBAAuB,CAAC;EACnC;AACF;AACA;AACA;AACA;AACA;EACE,MAAMC,2BAA2BA,CAAA,EAAkB;IACjD,OAAOH,sBAAsB,EAAEG,2BAA2B,CAAC,CAAC;EAC9D;;EAEA;AACF;AACA;AACA;EACE,MAAMC,0BAA0BA,CAAA,EAAkB;IAChD,OAAOJ,sBAAsB,EAAEI,0BAA0B,CAAC,CAAC;EAC7D;;EAEA;AACF;AACA;AACA;AACA;AACA;AACA;EACE,MAAMC,uBAAuBA,CAACC,YAAqB,EAAiB;IAClE,IAAIC,qBAAQ,CAACC,EAAE,KAAK,KAAK,EAAE;MACzB;IACF;IACA,OAAOR,sBAAsB,EAAEK,uBAAuB,CAACC,YAAY,CAAC;EACtE;;EAEA;AACF;AACA;EACE,MAAMG,sBAAsBA,CAAA,EAAkB;IAC5C,IAAIF,qBAAQ,CAACC,EAAE,KAAK,KAAK,EAAE;MACzB;IACF;IACA,OAAOR,sBAAsB,EAAES,sBAAsB,CAAC,CAAC;EACzD;AACF;AAACC,OAAA,CAAAR,uBAAA,GAAAA,uBAAA;AAEM,MAAMS,6BAA6B,GAAAD,OAAA,CAAAC,6BAAA,GAAG,IAAIT,uBAAuB,CAAC,CAAC","ignoreList":[]}
@@ -9,6 +9,7 @@ var _react = _interopRequireWildcard(require("react"));
9
9
  var _useIosCallkeepWithCallingStateEffect = require("../../hooks/push/useIosCallkeepWithCallingStateEffect");
10
10
  var _utils = require("../../utils/push/internal/utils");
11
11
  var _useAndroidKeepCallAliveEffect = require("../../hooks/useAndroidKeepCallAliveEffect");
12
+ var _useScreenShareAudioMixing = require("../../hooks/useScreenShareAudioMixing");
12
13
  var _AppStateListener = require("./AppStateListener");
13
14
  var _DeviceStats = require("./DeviceStats");
14
15
  var _constants = require("../../utils/push/internal/constants");
@@ -30,7 +31,7 @@ const StreamCall = ({
30
31
  }) => {
31
32
  return /*#__PURE__*/_react.default.createElement(_videoReactBindings.StreamCallProvider, {
32
33
  call: call
33
- }, /*#__PURE__*/_react.default.createElement(_AppStateListener.AppStateListener, null), /*#__PURE__*/_react.default.createElement(AndroidKeepCallAlive, null), /*#__PURE__*/_react.default.createElement(IosInformCallkeepCallEnd, null), /*#__PURE__*/_react.default.createElement(ClearPushWSSubscriptions, null), /*#__PURE__*/_react.default.createElement(_DeviceStats.DeviceStats, null), children);
34
+ }, /*#__PURE__*/_react.default.createElement(_AppStateListener.AppStateListener, null), /*#__PURE__*/_react.default.createElement(AndroidKeepCallAlive, null), /*#__PURE__*/_react.default.createElement(IosInformCallkeepCallEnd, null), /*#__PURE__*/_react.default.createElement(ClearPushWSSubscriptions, null), /*#__PURE__*/_react.default.createElement(ScreenShareAudioMixer, null), /*#__PURE__*/_react.default.createElement(_DeviceStats.DeviceStats, null), children);
34
35
  };
35
36
 
36
37
  /**
@@ -52,6 +53,15 @@ const IosInformCallkeepCallEnd = () => {
52
53
  return null;
53
54
  };
54
55
 
56
+ /**
57
+ * This is a renderless component to manage screen share audio mixing lifecycle.
58
+ * It starts/stops native audio mixing based on screen share status and audio preference.
59
+ */
60
+ const ScreenShareAudioMixer = () => {
61
+ (0, _useScreenShareAudioMixing.useScreenShareAudioMixing)();
62
+ return null;
63
+ };
64
+
55
65
  /**
56
66
  * This is a renderless component to clear all push ws event subscriptions
57
67
  * and set whether push ws subscriptions can be added or not.
@@ -1 +1 @@
1
- {"version":3,"names":["_videoReactBindings","require","_react","_interopRequireWildcard","_useIosCallkeepWithCallingStateEffect","_utils","_useAndroidKeepCallAliveEffect","_AppStateListener","_DeviceStats","_constants","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","StreamCall","children","createElement","StreamCallProvider","AppStateListener","AndroidKeepCallAlive","IosInformCallkeepCallEnd","ClearPushWSSubscriptions","DeviceStats","exports","useAndroidKeepCallAliveEffect","useIosCallkeepWithCallingStateEffect","useEffect","pushUnsubscriptionCallbacks","forEach","cbArray","cb","clear","canAddPushWSSubscriptionsRef","current"],"sourceRoot":"../../../../src","sources":["providers/StreamCall/index.tsx"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["_videoReactBindings","require","_react","_interopRequireWildcard","_useIosCallkeepWithCallingStateEffect","_utils","_useAndroidKeepCallAliveEffect","_useScreenShareAudioMixing","_AppStateListener","_DeviceStats","_constants","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","StreamCall","children","createElement","StreamCallProvider","AppStateListener","AndroidKeepCallAlive","IosInformCallkeepCallEnd","ClearPushWSSubscriptions","ScreenShareAudioMixer","DeviceStats","exports","useAndroidKeepCallAliveEffect","useIosCallkeepWithCallingStateEffect","useScreenShareAudioMixing","useEffect","pushUnsubscriptionCallbacks","forEach","cbArray","cb","clear","canAddPushWSSubscriptionsRef","current"],"sourceRoot":"../../../../src","sources":["providers/StreamCall/index.tsx"],"mappings":"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","ignoreList":[]}
@@ -4,5 +4,5 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.version = void 0;
7
- const version = exports.version = '1.30.4';
7
+ const version = exports.version = '1.31.0';
8
8
  //# sourceMappingURL=version.js.map
@@ -18,7 +18,8 @@ import { IconWrapper } from '../../../icons';
18
18
  */
19
19
  export const ScreenShareToggleButton = ({
20
20
  onScreenShareStartedHandler,
21
- onScreenShareStoppedHandler
21
+ onScreenShareStoppedHandler,
22
+ screenShareOptions
22
23
  }) => {
23
24
  const {
24
25
  theme: {
@@ -31,7 +32,7 @@ export const ScreenShareToggleButton = ({
31
32
  const {
32
33
  onPress,
33
34
  hasPublishedScreenShare
34
- } = useScreenShareButton(screenCapturePickerViewiOSRef, onScreenShareStartedHandler, onScreenShareStoppedHandler);
35
+ } = useScreenShareButton(screenCapturePickerViewiOSRef, onScreenShareStartedHandler, onScreenShareStoppedHandler, undefined, screenShareOptions);
35
36
  if (!onPress) return null;
36
37
  return /*#__PURE__*/React.createElement(CallControlsButton, {
37
38
  onPress: onPress,
@@ -1 +1 @@
1
- {"version":3,"names":["React","useRef","Platform","ScreenCapturePickerView","ScreenShare","StopScreenShare","CallControlsButton","useTheme","useScreenShareButton","IconWrapper","ScreenShareToggleButton","onScreenShareStartedHandler","onScreenShareStoppedHandler","theme","colors","screenShareToggleButton","variants","screenCapturePickerViewiOSRef","onPress","hasPublishedScreenShare","createElement","color","buttonWarning","buttonSecondary","style","container","svgContainer","size","iconSizes","md","iconPrimary","OS","ref"],"sourceRoot":"../../../../../src","sources":["components/Call/CallControls/ScreenShareToggleButton.tsx"],"mappings":"AAAA,OAAOA,KAAK,IAAIC,MAAM,QAAQ,OAAO;AACrC,SAASC,QAAQ,QAAQ,cAAc;AACvC,SAASC,uBAAuB,QAAQ,gCAAgC;AACxE,SAASC,WAAW,QAAQ,4BAA4B;AACxD,SAASC,eAAe,QAAQ,gCAAgC;AAChE,SAASC,kBAAkB,QAAQ,sBAAsB;AACzD,SAASC,QAAQ,QAAQ,gCAAgC;AACzD,SAASC,oBAAoB,QAAQ,qCAAqC;AAC1E,SAASC,WAAW,QAAQ,gBAAgB;;AAE5C;AACA;AACA;;AAcA;AACA;AACA;AACA;AACA,OAAO,MAAMC,uBAAuB,GAAGA,CAAC;EACtCC,2BAA2B;EAC3BC;AAC4B,CAAC,KAAK;EAClC,MAAM;IACJC,KAAK,EAAE;MAAEC,MAAM;MAAEC,uBAAuB;MAAEC;IAAS;EACrD,CAAC,GAAGT,QAAQ,CAAC,CAAC;EAEd,MAAMU,6BAA6B,GAAGhB,MAAM,CAAC,IAAI,CAAC;EAElD,MAAM;IAAEiB,OAAO;IAAEC;EAAwB,CAAC,GAAGX,oBAAoB,CAC/DS,6BAA6B,EAC7BN,2BAA2B,EAC3BC,2BACF,CAAC;EAED,IAAI,CAACM,OAAO,EAAE,OAAO,IAAI;EAEzB,oBACElB,KAAA,CAAAoB,aAAA,CAACd,kBAAkB;IACjBY,OAAO,EAAEA,OAAQ;IACjBG,KAAK,EACHF,uBAAuB,GAAGL,MAAM,CAACQ,aAAa,GAAGR,MAAM,CAACS,eACzD;IACDC,KAAK,EAAE;MACLC,SAAS,EAAEV,uBAAuB,CAACU,SAAS;MAC5CC,YAAY,EAAEX,uBAAuB,CAACW;IACxC;EAAE,gBAEF1B,KAAA,CAAAoB,aAAA,CAACX,WAAW,QACTU,uBAAuB,gBACtBnB,KAAA,CAAAoB,aAAA,CAACf,eAAe;IACdsB,IAAI,EAAEX,QAAQ,CAACY,SAAS,CAACC,EAAG;IAC5BR,KAAK,EAAEP,MAAM,CAACgB;EAAY,CAC3B,CAAC,gBAEF9B,KAAA,CAAAoB,aAAA,CAAChB,WAAW;IACVuB,IAAI,EAAEX,QAAQ,CAACY,SAAS,CAACC,EAAG;IAC5BR,KAAK,EAAEP,MAAM,CAACgB;EAAY,CAC3B,CAEQ,CAAC,EACb5B,QAAQ,CAAC6B,EAAE,KAAK,KAAK,iBACpB/B,KAAA,CAAAoB,aAAA,CAACjB,uBAAuB;IAAC6B,GAAG,EAAEf;EAA8B,CAAE,CAE9C,CAAC;AAEzB,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["React","useRef","Platform","ScreenCapturePickerView","ScreenShare","StopScreenShare","CallControlsButton","useTheme","useScreenShareButton","IconWrapper","ScreenShareToggleButton","onScreenShareStartedHandler","onScreenShareStoppedHandler","screenShareOptions","theme","colors","screenShareToggleButton","variants","screenCapturePickerViewiOSRef","onPress","hasPublishedScreenShare","undefined","createElement","color","buttonWarning","buttonSecondary","style","container","svgContainer","size","iconSizes","md","iconPrimary","OS","ref"],"sourceRoot":"../../../../../src","sources":["components/Call/CallControls/ScreenShareToggleButton.tsx"],"mappings":"AAAA,OAAOA,KAAK,IAAIC,MAAM,QAAQ,OAAO;AACrC,SAASC,QAAQ,QAAQ,cAAc;AACvC,SAASC,uBAAuB,QAAQ,gCAAgC;AACxE,SAASC,WAAW,QAAQ,4BAA4B;AACxD,SAASC,eAAe,QAAQ,gCAAgC;AAChE,SAASC,kBAAkB,QAAQ,sBAAsB;AACzD,SAASC,QAAQ,QAAQ,gCAAgC;AACzD,SACEC,oBAAoB,QAEf,qCAAqC;AAC5C,SAASC,WAAW,QAAQ,gBAAgB;;AAE5C;AACA;AACA;;AAkBA;AACA;AACA;AACA;AACA,OAAO,MAAMC,uBAAuB,GAAGA,CAAC;EACtCC,2BAA2B;EAC3BC,2BAA2B;EAC3BC;AAC4B,CAAC,KAAK;EAClC,MAAM;IACJC,KAAK,EAAE;MAAEC,MAAM;MAAEC,uBAAuB;MAAEC;IAAS;EACrD,CAAC,GAAGV,QAAQ,CAAC,CAAC;EAEd,MAAMW,6BAA6B,GAAGjB,MAAM,CAAC,IAAI,CAAC;EAElD,MAAM;IAAEkB,OAAO;IAAEC;EAAwB,CAAC,GAAGZ,oBAAoB,CAC/DU,6BAA6B,EAC7BP,2BAA2B,EAC3BC,2BAA2B,EAC3BS,SAAS,EACTR,kBACF,CAAC;EAED,IAAI,CAACM,OAAO,EAAE,OAAO,IAAI;EAEzB,oBACEnB,KAAA,CAAAsB,aAAA,CAAChB,kBAAkB;IACjBa,OAAO,EAAEA,OAAQ;IACjBI,KAAK,EACHH,uBAAuB,GAAGL,MAAM,CAACS,aAAa,GAAGT,MAAM,CAACU,eACzD;IACDC,KAAK,EAAE;MACLC,SAAS,EAAEX,uBAAuB,CAACW,SAAS;MAC5CC,YAAY,EAAEZ,uBAAuB,CAACY;IACxC;EAAE,gBAEF5B,KAAA,CAAAsB,aAAA,CAACb,WAAW,QACTW,uBAAuB,gBACtBpB,KAAA,CAAAsB,aAAA,CAACjB,eAAe;IACdwB,IAAI,EAAEZ,QAAQ,CAACa,SAAS,CAACC,EAAG;IAC5BR,KAAK,EAAER,MAAM,CAACiB;EAAY,CAC3B,CAAC,gBAEFhC,KAAA,CAAAsB,aAAA,CAAClB,WAAW;IACVyB,IAAI,EAAEZ,QAAQ,CAACa,SAAS,CAACC,EAAG;IAC5BR,KAAK,EAAER,MAAM,CAACiB;EAAY,CAC3B,CAEQ,CAAC,EACb9B,QAAQ,CAAC+B,EAAE,KAAK,KAAK,iBACpBjC,KAAA,CAAAsB,aAAA,CAACnB,uBAAuB;IAAC+B,GAAG,EAAEhB;EAA8B,CAAE,CAE9C,CAAC;AAEzB,CAAC","ignoreList":[]}
@@ -6,6 +6,7 @@ export * from './useIsIosScreenshareBroadcastStarted';
6
6
  export * from './useIsInPiPMode';
7
7
  export * from './useAutoEnterPiPEffect';
8
8
  export * from './useScreenShareButton';
9
+ export * from './useScreenShareAudioMixing';
9
10
  export * from './useTrackDimensions';
10
11
  export * from './useScreenshot';
11
12
  export * from './useSpeechDetection';
@@ -1 +1 @@
1
- {"version":3,"names":[],"sourceRoot":"../../../src","sources":["hooks/index.ts"],"mappings":"AAAA,cAAc,wBAAwB;AACtC,cAAc,6BAA6B;AAC3C,cAAc,QAAQ;AACtB,cAAc,iCAAiC;AAC/C,cAAc,uCAAuC;AACrD,cAAc,kBAAkB;AAChC,cAAc,yBAAyB;AACvC,cAAc,wBAAwB;AACtC,cAAc,sBAAsB;AACpC,cAAc,iBAAiB;AAC/B,cAAc,sBAAsB;AACpC,cAAc,iBAAiB","ignoreList":[]}
1
+ {"version":3,"names":[],"sourceRoot":"../../../src","sources":["hooks/index.ts"],"mappings":"AAAA,cAAc,wBAAwB;AACtC,cAAc,6BAA6B;AAC3C,cAAc,QAAQ;AACtB,cAAc,iCAAiC;AAC/C,cAAc,uCAAuC;AACrD,cAAc,kBAAkB;AAChC,cAAc,yBAAyB;AACvC,cAAc,wBAAwB;AACtC,cAAc,6BAA6B;AAC3C,cAAc,sBAAsB;AACpC,cAAc,iBAAiB;AAC/B,cAAc,sBAAsB;AACpC,cAAc,iBAAiB","ignoreList":[]}
@@ -0,0 +1,119 @@
1
+ import { useCallback, useEffect, useRef, useState } from 'react';
2
+ import { hasScreenShare, videoLoggerSystem } from '@stream-io/video-client';
3
+ import { useCall, useCallStateHooks } from '@stream-io/video-react-bindings';
4
+ import { screenShareAudioMixingManager } from '../modules/ScreenShareAudioManager';
5
+ import { NoiseCancellationWrapper } from '../providers/NoiseCancellation/lib';
6
+ const logger = videoLoggerSystem.getLogger('useScreenShareAudioMixing');
7
+
8
+ /**
9
+ * Tries to disable noise cancellation so screen audio passes through
10
+ * unfiltered. Returns true if NC was disabled (and should be re-enabled later).
11
+ */
12
+ async function disableNoiseCancellation() {
13
+ try {
14
+ const nc = NoiseCancellationWrapper.getInstance();
15
+ const wasEnabled = await nc.isEnabled();
16
+ if (wasEnabled) {
17
+ await nc.disable();
18
+ logger.info('Noise cancellation disabled for screen share audio');
19
+ }
20
+ return wasEnabled;
21
+ } catch {
22
+ // NC module not installed or not configured — nothing to do
23
+ return false;
24
+ }
25
+ }
26
+
27
+ /**
28
+ * Re-enables noise cancellation if it was previously disabled.
29
+ */
30
+ async function restoreNoiseCancellation() {
31
+ try {
32
+ const nc = NoiseCancellationWrapper.getInstance();
33
+ await nc.enable();
34
+ logger.info('Noise cancellation re-enabled after screen share audio');
35
+ } catch {
36
+ // NC module not installed — nothing to do
37
+ }
38
+ }
39
+
40
+ /**
41
+ * Hook that manages the lifecycle of screen share audio mixing.
42
+ *
43
+ * When screen share is active and audio mixing is enabled
44
+ * (via `call.screenShare.enableScreenShareAudio()`), this hook
45
+ * calls the native module to mix captured screen/app audio
46
+ * into the microphone audio track.
47
+ *
48
+ * Noise cancellation is temporarily disabled while screen audio mixing
49
+ * is active so that all captured sounds (music, game audio, etc.)
50
+ * pass through without being filtered.
51
+ */
52
+ export const useScreenShareAudioMixing = () => {
53
+ const call = useCall();
54
+ const {
55
+ useLocalParticipant
56
+ } = useCallStateHooks();
57
+ const localParticipant = useLocalParticipant();
58
+ const isScreenSharing = localParticipant != null && hasScreenShare(localParticipant);
59
+ const [audioEnabled, setAudioEnabled] = useState(() => call?.screenShare.state.audioEnabled ?? false);
60
+ const isMixingActiveRef = useRef(false);
61
+ const ncWasEnabledRef = useRef(false);
62
+ useEffect(() => {
63
+ if (!call) return;
64
+ const sub = call.screenShare.state.audioEnabled$.subscribe(setAudioEnabled);
65
+ return () => sub.unsubscribe();
66
+ }, [call]);
67
+ const startMixing = useCallback(async () => {
68
+ if (isMixingActiveRef.current) return;
69
+ try {
70
+ // Disable NC before starting mixing so screen audio is not filtered
71
+ ncWasEnabledRef.current = await disableNoiseCancellation();
72
+ logger.info('Starting screen share audio mixing');
73
+ await screenShareAudioMixingManager.startScreenShareAudioMixing();
74
+ isMixingActiveRef.current = true;
75
+ } catch (error) {
76
+ logger.warn('Failed to start screen share audio mixing', error);
77
+ if (ncWasEnabledRef.current) {
78
+ restoreNoiseCancellation().catch(() => {});
79
+ ncWasEnabledRef.current = false;
80
+ }
81
+ }
82
+ }, []);
83
+ const stopMixing = useCallback(async () => {
84
+ if (!isMixingActiveRef.current) return;
85
+ try {
86
+ logger.info('Stopping screen share audio mixing');
87
+ await screenShareAudioMixingManager.stopScreenShareAudioMixing();
88
+ isMixingActiveRef.current = false;
89
+ if (ncWasEnabledRef.current) {
90
+ await restoreNoiseCancellation();
91
+ ncWasEnabledRef.current = false;
92
+ }
93
+ } catch (error) {
94
+ logger.warn('Failed to stop screen share audio mixing', error);
95
+ }
96
+ }, []);
97
+
98
+ // Start/stop audio mixing based on screen share status and audio preference
99
+ useEffect(() => {
100
+ if (isScreenSharing && audioEnabled) {
101
+ startMixing();
102
+ } else {
103
+ stopMixing();
104
+ }
105
+ }, [isScreenSharing, audioEnabled, startMixing, stopMixing]);
106
+ useEffect(() => {
107
+ return () => {
108
+ if (isMixingActiveRef.current) {
109
+ screenShareAudioMixingManager.stopScreenShareAudioMixing().catch(() => {});
110
+ isMixingActiveRef.current = false;
111
+ if (ncWasEnabledRef.current) {
112
+ restoreNoiseCancellation().catch(() => {});
113
+ ncWasEnabledRef.current = false;
114
+ }
115
+ }
116
+ };
117
+ }, []);
118
+ };
119
+ //# sourceMappingURL=useScreenShareAudioMixing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["useCallback","useEffect","useRef","useState","hasScreenShare","videoLoggerSystem","useCall","useCallStateHooks","screenShareAudioMixingManager","NoiseCancellationWrapper","logger","getLogger","disableNoiseCancellation","nc","getInstance","wasEnabled","isEnabled","disable","info","restoreNoiseCancellation","enable","useScreenShareAudioMixing","call","useLocalParticipant","localParticipant","isScreenSharing","audioEnabled","setAudioEnabled","screenShare","state","isMixingActiveRef","ncWasEnabledRef","sub","audioEnabled$","subscribe","unsubscribe","startMixing","current","startScreenShareAudioMixing","error","warn","catch","stopMixing","stopScreenShareAudioMixing"],"sourceRoot":"../../../src","sources":["hooks/useScreenShareAudioMixing.ts"],"mappings":"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","ignoreList":[]}
@@ -4,10 +4,26 @@ import { useEffect, useRef } from 'react';
4
4
  import { findNodeHandle, NativeModules, Platform } from 'react-native';
5
5
  import { usePrevious } from '../utils/hooks';
6
6
  import { useIsIosScreenshareBroadcastStarted } from './useIsIosScreenshareBroadcastStarted';
7
+ import { screenShareAudioMixingManager } from '../modules/ScreenShareAudioManager';
8
+
9
+ /**
10
+ * The type of screen sharing to use on iOS.
11
+ *
12
+ * - `'broadcast'` — Uses a Broadcast Upload Extension (RPSystemBroadcastPickerView).
13
+ * Captures the entire device screen, works across all apps. Requires an extension target.
14
+ * - `'inApp'` — Uses RPScreenRecorder.startCapture to capture the current app's screen.
15
+ * Only captures the current app. Supports `.audioApp` sample buffers for audio mixing.
16
+ *
17
+ * On Android, this option is ignored — the system screen capture dialog is always used.
18
+ */
19
+
20
+ /**
21
+ * Options for screen share behavior.
22
+ */
7
23
 
8
24
  // ios >= 14.0 or android - platform restrictions
9
25
  const CanDeviceScreenShare = Platform.OS === 'ios' && Number.parseInt(Platform.Version?.split('.')[0] ?? '0', 10) >= 14 || Platform.OS === 'android';
10
- export const useScreenShareButton = (screenCapturePickerViewiOSRef, onScreenShareStartedHandler, onScreenShareStoppedHandler, onMissingScreenShareStreamPermission) => {
26
+ export const useScreenShareButton = (screenCapturePickerViewiOSRef, onScreenShareStartedHandler, onScreenShareStoppedHandler, onMissingScreenShareStreamPermission, screenShareOptions) => {
11
27
  const call = useCall();
12
28
  const {
13
29
  useLocalParticipant,
@@ -18,6 +34,8 @@ export const useScreenShareButton = (screenCapturePickerViewiOSRef, onScreenShar
18
34
  const ownCapabilities = useOwnCapabilities();
19
35
  const hasScreenSharingPermissions = ownCapabilities?.includes(OwnCapability.SCREENSHARE);
20
36
  const isScreenSharingEnabledInCall = callSettings?.screensharing.enabled;
37
+ const screenShareType = screenShareOptions?.type ?? 'broadcast';
38
+ const includeAudio = screenShareOptions?.includeAudio ?? false;
21
39
  const onScreenShareStartedHandlerRef = useRef(onScreenShareStartedHandler);
22
40
  onScreenShareStartedHandlerRef.current = onScreenShareStartedHandler;
23
41
  const onScreenShareStoppedHandlerRef = useRef(onScreenShareStoppedHandler);
@@ -28,31 +46,63 @@ export const useScreenShareButton = (screenCapturePickerViewiOSRef, onScreenShar
28
46
  const hasPublishedScreenShare = localParticipant && hasScreenShare(localParticipant);
29
47
 
30
48
  // listens to iOS screen share broadcast started event from the system
49
+ // (only relevant for broadcast mode)
31
50
  useEffect(() => {
32
51
  if (Platform.OS !== 'ios') {
33
52
  return;
34
53
  }
54
+ if (screenShareType !== 'broadcast') {
55
+ return;
56
+ }
35
57
  if (iosScreenShareStartedFromSystem && !prevIosScreenShareStartedFromSystem) {
36
58
  onScreenShareStartedHandlerRef.current?.();
59
+ if (includeAudio) {
60
+ call?.screenShare.enableScreenShareAudio();
61
+ }
37
62
  call?.screenShare.enable();
38
63
  } else if (!iosScreenShareStartedFromSystem && prevIosScreenShareStartedFromSystem) {
39
64
  onScreenShareStoppedHandlerRef.current?.();
40
65
  call?.screenShare.disable(true);
41
66
  }
42
- }, [call, iosScreenShareStartedFromSystem, prevIosScreenShareStartedFromSystem]);
67
+ }, [call, includeAudio, screenShareType, iosScreenShareStartedFromSystem, prevIosScreenShareStartedFromSystem]);
43
68
  const onPress = async () => {
44
69
  if (!hasScreenSharingPermissions) {
45
70
  const logger = videoLoggerSystem.getLogger('useScreenShareButton');
46
71
  logger.info('User does not have permissions to stream the screen share media, calling onMissingScreenShareStreamPermission handler if present');
47
72
  onMissingScreenShareStreamPermission?.();
73
+ return;
48
74
  }
49
75
  if (!hasPublishedScreenShare) {
50
- if (Platform.OS === 'ios') {
76
+ // Set audio mixing preference before starting screen share
77
+ if (includeAudio) {
78
+ call?.screenShare.enableScreenShareAudio();
79
+ } else {
80
+ try {
81
+ await call?.screenShare.disableScreenShareAudio();
82
+ } catch (error) {
83
+ const logger = videoLoggerSystem.getLogger('useScreenShareButton');
84
+ logger.warn('Failed to disable screen share audio', error);
85
+ }
86
+ }
87
+ if (Platform.OS === 'ios' && screenShareType === 'inApp') {
88
+ // In-app screen sharing on iOS — uses RPScreenRecorder directly
89
+ try {
90
+ await screenShareAudioMixingManager.startInAppScreenCapture(includeAudio);
91
+ await call?.screenShare.enable();
92
+ onScreenShareStartedHandler?.();
93
+ } catch (error) {
94
+ await screenShareAudioMixingManager.stopInAppScreenCapture();
95
+ const logger = videoLoggerSystem.getLogger('useScreenShareButton');
96
+ logger.warn('Failed to start in-app screen capture', error);
97
+ }
98
+ } else if (Platform.OS === 'ios') {
99
+ // Broadcast screen sharing on iOS — shows the system picker
51
100
  const reactTag = findNodeHandle(screenCapturePickerViewiOSRef.current);
52
101
  await NativeModules.ScreenCapturePickerViewManager.show(reactTag);
53
102
  // After this the iOS screen share broadcast started/stopped event will be triggered
54
103
  // and the useEffect listener will handle the rest
55
104
  } else {
105
+ // Android screen sharing
56
106
  try {
57
107
  await call?.screenShare.enable();
58
108
  onScreenShareStartedHandler?.();
@@ -64,6 +114,10 @@ export const useScreenShareButton = (screenCapturePickerViewiOSRef, onScreenShar
64
114
  }
65
115
  } else if (hasPublishedScreenShare) {
66
116
  onScreenShareStoppedHandler?.();
117
+ // Stop in-app screen capture if it was active (iOS only)
118
+ if (Platform.OS === 'ios' && screenShareType === 'inApp') {
119
+ await screenShareAudioMixingManager.stopInAppScreenCapture();
120
+ }
67
121
  await call?.screenShare.disable(true);
68
122
  }
69
123
  };
@@ -1 +1 @@
1
- {"version":3,"names":["hasScreenShare","OwnCapability","videoLoggerSystem","useCall","useCallStateHooks","useEffect","useRef","findNodeHandle","NativeModules","Platform","usePrevious","useIsIosScreenshareBroadcastStarted","CanDeviceScreenShare","OS","Number","parseInt","Version","split","useScreenShareButton","screenCapturePickerViewiOSRef","onScreenShareStartedHandler","onScreenShareStoppedHandler","onMissingScreenShareStreamPermission","call","useLocalParticipant","useCallSettings","useOwnCapabilities","callSettings","ownCapabilities","hasScreenSharingPermissions","includes","SCREENSHARE","isScreenSharingEnabledInCall","screensharing","enabled","onScreenShareStartedHandlerRef","current","onScreenShareStoppedHandlerRef","iosScreenShareStartedFromSystem","prevIosScreenShareStartedFromSystem","localParticipant","hasPublishedScreenShare","screenShare","enable","disable","onPress","logger","getLogger","info","reactTag","ScreenCapturePickerViewManager","show","error","undefined"],"sourceRoot":"../../../src","sources":["hooks/useScreenShareButton.ts"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["hasScreenShare","OwnCapability","videoLoggerSystem","useCall","useCallStateHooks","useEffect","useRef","findNodeHandle","NativeModules","Platform","usePrevious","useIsIosScreenshareBroadcastStarted","screenShareAudioMixingManager","CanDeviceScreenShare","OS","Number","parseInt","Version","split","useScreenShareButton","screenCapturePickerViewiOSRef","onScreenShareStartedHandler","onScreenShareStoppedHandler","onMissingScreenShareStreamPermission","screenShareOptions","call","useLocalParticipant","useCallSettings","useOwnCapabilities","callSettings","ownCapabilities","hasScreenSharingPermissions","includes","SCREENSHARE","isScreenSharingEnabledInCall","screensharing","enabled","screenShareType","type","includeAudio","onScreenShareStartedHandlerRef","current","onScreenShareStoppedHandlerRef","iosScreenShareStartedFromSystem","prevIosScreenShareStartedFromSystem","localParticipant","hasPublishedScreenShare","screenShare","enableScreenShareAudio","enable","disable","onPress","logger","getLogger","info","disableScreenShareAudio","error","warn","startInAppScreenCapture","stopInAppScreenCapture","reactTag","ScreenCapturePickerViewManager","show","undefined"],"sourceRoot":"../../../src","sources":["hooks/useScreenShareButton.ts"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,47 @@
1
+ import { NativeModules, Platform } from 'react-native';
2
+ const StreamVideoReactNative = NativeModules.StreamVideoReactNative;
3
+ export class ScreenShareAudioManager {
4
+ /**
5
+ * Starts mixing screen share audio into the microphone audio track.
6
+ * On iOS, this enables audio buffer processing on the prepared mixer.
7
+ * On Android, this registers an audio processor that captures system media
8
+ * audio via AudioPlaybackCaptureConfiguration and mixes it into the mic buffer.
9
+ */
10
+ async startScreenShareAudioMixing() {
11
+ return StreamVideoReactNative?.startScreenShareAudioMixing();
12
+ }
13
+
14
+ /**
15
+ * Stops mixing screen share audio into the microphone audio track
16
+ * and restores the original audio pipeline.
17
+ */
18
+ async stopScreenShareAudioMixing() {
19
+ return StreamVideoReactNative?.stopScreenShareAudioMixing();
20
+ }
21
+
22
+ /**
23
+ * Starts in-app screen capture using RPScreenRecorder (iOS only).
24
+ * Unlike broadcast screen sharing, in-app capture runs in the main app process
25
+ * and can directly provide `.audioApp` sample buffers for mixing.
26
+ *
27
+ * @param includeAudio Whether to capture and mix app audio.
28
+ */
29
+ async startInAppScreenCapture(includeAudio) {
30
+ if (Platform.OS !== 'ios') {
31
+ return;
32
+ }
33
+ return StreamVideoReactNative?.startInAppScreenCapture(includeAudio);
34
+ }
35
+
36
+ /**
37
+ * Stops in-app screen capture (iOS only).
38
+ */
39
+ async stopInAppScreenCapture() {
40
+ if (Platform.OS !== 'ios') {
41
+ return;
42
+ }
43
+ return StreamVideoReactNative?.stopInAppScreenCapture();
44
+ }
45
+ }
46
+ export const screenShareAudioMixingManager = new ScreenShareAudioManager();
47
+ //# sourceMappingURL=ScreenShareAudioManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["NativeModules","Platform","StreamVideoReactNative","ScreenShareAudioManager","startScreenShareAudioMixing","stopScreenShareAudioMixing","startInAppScreenCapture","includeAudio","OS","stopInAppScreenCapture","screenShareAudioMixingManager"],"sourceRoot":"../../../src","sources":["modules/ScreenShareAudioManager.ts"],"mappings":"AAAA,SAASA,aAAa,EAAEC,QAAQ,QAAQ,cAAc;AAEtD,MAAMC,sBAAsB,GAAGF,aAAa,CAACE,sBAAsB;AAEnE,OAAO,MAAMC,uBAAuB,CAAC;EACnC;AACF;AACA;AACA;AACA;AACA;EACE,MAAMC,2BAA2BA,CAAA,EAAkB;IACjD,OAAOF,sBAAsB,EAAEE,2BAA2B,CAAC,CAAC;EAC9D;;EAEA;AACF;AACA;AACA;EACE,MAAMC,0BAA0BA,CAAA,EAAkB;IAChD,OAAOH,sBAAsB,EAAEG,0BAA0B,CAAC,CAAC;EAC7D;;EAEA;AACF;AACA;AACA;AACA;AACA;AACA;EACE,MAAMC,uBAAuBA,CAACC,YAAqB,EAAiB;IAClE,IAAIN,QAAQ,CAACO,EAAE,KAAK,KAAK,EAAE;MACzB;IACF;IACA,OAAON,sBAAsB,EAAEI,uBAAuB,CAACC,YAAY,CAAC;EACtE;;EAEA;AACF;AACA;EACE,MAAME,sBAAsBA,CAAA,EAAkB;IAC5C,IAAIR,QAAQ,CAACO,EAAE,KAAK,KAAK,EAAE;MACzB;IACF;IACA,OAAON,sBAAsB,EAAEO,sBAAsB,CAAC,CAAC;EACzD;AACF;AAEA,OAAO,MAAMC,6BAA6B,GAAG,IAAIP,uBAAuB,CAAC,CAAC","ignoreList":[]}
@@ -3,6 +3,7 @@ import React, { useEffect } from 'react';
3
3
  import { useIosCallkeepWithCallingStateEffect } from '../../hooks/push/useIosCallkeepWithCallingStateEffect';
4
4
  import { canAddPushWSSubscriptionsRef } from '../../utils/push/internal/utils';
5
5
  import { useAndroidKeepCallAliveEffect } from '../../hooks/useAndroidKeepCallAliveEffect';
6
+ import { useScreenShareAudioMixing } from '../../hooks/useScreenShareAudioMixing';
6
7
  import { AppStateListener } from './AppStateListener';
7
8
  import { DeviceStats } from './DeviceStats';
8
9
  import { pushUnsubscriptionCallbacks } from '../../utils/push/internal/constants';
@@ -24,7 +25,7 @@ export const StreamCall = ({
24
25
  }) => {
25
26
  return /*#__PURE__*/React.createElement(StreamCallProvider, {
26
27
  call: call
27
- }, /*#__PURE__*/React.createElement(AppStateListener, null), /*#__PURE__*/React.createElement(AndroidKeepCallAlive, null), /*#__PURE__*/React.createElement(IosInformCallkeepCallEnd, null), /*#__PURE__*/React.createElement(ClearPushWSSubscriptions, null), /*#__PURE__*/React.createElement(DeviceStats, null), children);
28
+ }, /*#__PURE__*/React.createElement(AppStateListener, null), /*#__PURE__*/React.createElement(AndroidKeepCallAlive, null), /*#__PURE__*/React.createElement(IosInformCallkeepCallEnd, null), /*#__PURE__*/React.createElement(ClearPushWSSubscriptions, null), /*#__PURE__*/React.createElement(ScreenShareAudioMixer, null), /*#__PURE__*/React.createElement(DeviceStats, null), children);
28
29
  };
29
30
 
30
31
  /**
@@ -45,6 +46,15 @@ const IosInformCallkeepCallEnd = () => {
45
46
  return null;
46
47
  };
47
48
 
49
+ /**
50
+ * This is a renderless component to manage screen share audio mixing lifecycle.
51
+ * It starts/stops native audio mixing based on screen share status and audio preference.
52
+ */
53
+ const ScreenShareAudioMixer = () => {
54
+ useScreenShareAudioMixing();
55
+ return null;
56
+ };
57
+
48
58
  /**
49
59
  * This is a renderless component to clear all push ws event subscriptions
50
60
  * and set whether push ws subscriptions can be added or not.
@@ -1 +1 @@
1
- {"version":3,"names":["StreamCallProvider","React","useEffect","useIosCallkeepWithCallingStateEffect","canAddPushWSSubscriptionsRef","useAndroidKeepCallAliveEffect","AppStateListener","DeviceStats","pushUnsubscriptionCallbacks","StreamCall","call","children","createElement","AndroidKeepCallAlive","IosInformCallkeepCallEnd","ClearPushWSSubscriptions","forEach","cbArray","cb","clear","current"],"sourceRoot":"../../../../src","sources":["providers/StreamCall/index.tsx"],"mappings":"AAAA,SAASA,kBAAkB,QAAQ,iCAAiC;AACpE,OAAOC,KAAK,IAA4BC,SAAS,QAAQ,OAAO;AAEhE,SAASC,oCAAoC,QAAQ,uDAAuD;AAC5G,SAASC,4BAA4B,QAAQ,iCAAiC;AAC9E,SAASC,6BAA6B,QAAQ,2CAA2C;AACzF,SAASC,gBAAgB,QAAQ,oBAAoB;AACrD,SAASC,WAAW,QAAQ,eAAe;AAC3C,SAASC,2BAA2B,QAAQ,qCAAqC;;AAEjF;;AAEA;;AASA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMC,UAAU,GAAGA,CAAC;EACzBC,IAAI;EACJC;AACkC,CAAC,KAAK;EACxC,oBACEV,KAAA,CAAAW,aAAA,CAACZ,kBAAkB;IAACU,IAAI,EAAEA;EAAK,gBAC7BT,KAAA,CAAAW,aAAA,CAACN,gBAAgB,MAAE,CAAC,eACpBL,KAAA,CAAAW,aAAA,CAACC,oBAAoB,MAAE,CAAC,eACxBZ,KAAA,CAAAW,aAAA,CAACE,wBAAwB,MAAE,CAAC,eAC5Bb,KAAA,CAAAW,aAAA,CAACG,wBAAwB,MAAE,CAAC,eAC5Bd,KAAA,CAAAW,aAAA,CAACL,WAAW,MAAE,CAAC,EACdI,QACiB,CAAC;AAEzB,CAAC;;AAED;AACA;AACA;AACA;AACA,MAAME,oBAAoB,GAAGA,CAAA,KAAM;EACjCR,6BAA6B,CAAC,CAAC;EAC/B,OAAO,IAAI;AACb,CAAC;;AAED;AACA;AACA;AACA;AACA,MAAMS,wBAAwB,GAAGA,CAAA,KAAM;EACrCX,oCAAoC,CAAC,CAAC;EACtC,OAAO,IAAI;AACb,CAAC;;AAED;AACA;AACA;AACA;AACA,MAAMY,wBAAwB,GAAGA,CAAA,KAAM;EACrCb,SAAS,CAAC,MAAM;IACd;IACAM,2BAA2B,CAACQ,OAAO,CAAEC,OAAO,IAC1CA,OAAO,CAACD,OAAO,CAAEE,EAAE,IAAKA,EAAE,CAAC,CAAC,CAC9B,CAAC;IACDV,2BAA2B,CAACW,KAAK,CAAC,CAAC;IACnCf,4BAA4B,CAACgB,OAAO,GAAG,KAAK;IAC5C,OAAO,MAAM;MACXhB,4BAA4B,CAACgB,OAAO,GAAG,IAAI;IAC7C,CAAC;EACH,CAAC,EAAE,EAAE,CAAC;EACN,OAAO,IAAI;AACb,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["StreamCallProvider","React","useEffect","useIosCallkeepWithCallingStateEffect","canAddPushWSSubscriptionsRef","useAndroidKeepCallAliveEffect","useScreenShareAudioMixing","AppStateListener","DeviceStats","pushUnsubscriptionCallbacks","StreamCall","call","children","createElement","AndroidKeepCallAlive","IosInformCallkeepCallEnd","ClearPushWSSubscriptions","ScreenShareAudioMixer","forEach","cbArray","cb","clear","current"],"sourceRoot":"../../../../src","sources":["providers/StreamCall/index.tsx"],"mappings":"AAAA,SAASA,kBAAkB,QAAQ,iCAAiC;AACpE,OAAOC,KAAK,IAA4BC,SAAS,QAAQ,OAAO;AAEhE,SAASC,oCAAoC,QAAQ,uDAAuD;AAC5G,SAASC,4BAA4B,QAAQ,iCAAiC;AAC9E,SAASC,6BAA6B,QAAQ,2CAA2C;AACzF,SAASC,yBAAyB,QAAQ,uCAAuC;AACjF,SAASC,gBAAgB,QAAQ,oBAAoB;AACrD,SAASC,WAAW,QAAQ,eAAe;AAC3C,SAASC,2BAA2B,QAAQ,qCAAqC;;AAEjF;;AAEA;;AASA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMC,UAAU,GAAGA,CAAC;EACzBC,IAAI;EACJC;AACkC,CAAC,KAAK;EACxC,oBACEX,KAAA,CAAAY,aAAA,CAACb,kBAAkB;IAACW,IAAI,EAAEA;EAAK,gBAC7BV,KAAA,CAAAY,aAAA,CAACN,gBAAgB,MAAE,CAAC,eACpBN,KAAA,CAAAY,aAAA,CAACC,oBAAoB,MAAE,CAAC,eACxBb,KAAA,CAAAY,aAAA,CAACE,wBAAwB,MAAE,CAAC,eAC5Bd,KAAA,CAAAY,aAAA,CAACG,wBAAwB,MAAE,CAAC,eAC5Bf,KAAA,CAAAY,aAAA,CAACI,qBAAqB,MAAE,CAAC,eACzBhB,KAAA,CAAAY,aAAA,CAACL,WAAW,MAAE,CAAC,EACdI,QACiB,CAAC;AAEzB,CAAC;;AAED;AACA;AACA;AACA;AACA,MAAME,oBAAoB,GAAGA,CAAA,KAAM;EACjCT,6BAA6B,CAAC,CAAC;EAC/B,OAAO,IAAI;AACb,CAAC;;AAED;AACA;AACA;AACA;AACA,MAAMU,wBAAwB,GAAGA,CAAA,KAAM;EACrCZ,oCAAoC,CAAC,CAAC;EACtC,OAAO,IAAI;AACb,CAAC;;AAED;AACA;AACA;AACA;AACA,MAAMc,qBAAqB,GAAGA,CAAA,KAAM;EAClCX,yBAAyB,CAAC,CAAC;EAC3B,OAAO,IAAI;AACb,CAAC;;AAED;AACA;AACA;AACA;AACA,MAAMU,wBAAwB,GAAGA,CAAA,KAAM;EACrCd,SAAS,CAAC,MAAM;IACd;IACAO,2BAA2B,CAACS,OAAO,CAAEC,OAAO,IAC1CA,OAAO,CAACD,OAAO,CAAEE,EAAE,IAAKA,EAAE,CAAC,CAAC,CAC9B,CAAC;IACDX,2BAA2B,CAACY,KAAK,CAAC,CAAC;IACnCjB,4BAA4B,CAACkB,OAAO,GAAG,KAAK;IAC5C,OAAO,MAAM;MACXlB,4BAA4B,CAACkB,OAAO,GAAG,IAAI;IAC7C,CAAC;EACH,CAAC,EAAE,EAAE,CAAC;EACN,OAAO,IAAI;AACb,CAAC","ignoreList":[]}
@@ -1,2 +1,2 @@
1
- export const version = '1.30.4';
1
+ export const version = '1.31.0';
2
2
  //# sourceMappingURL=version.js.map
@@ -1,4 +1,5 @@
1
1
  import React from 'react';
2
+ import { type ScreenShareOptions } from '../../../hooks/useScreenShareButton';
2
3
  /**
3
4
  * The props for the Screen Share button in the Call Controls.
4
5
  */
@@ -13,10 +14,14 @@ export type ScreenShareToggleButtonProps = {
13
14
  *
14
15
  */
15
16
  onScreenShareStoppedHandler?: () => void;
17
+ /**
18
+ * Options for screen share behavior (type, includeAudio).
19
+ */
20
+ screenShareOptions?: ScreenShareOptions;
16
21
  };
17
22
  /**
18
23
  * Button to start/stop screen share.
19
24
  * Note: This button is enabled only on iOS >= 14.0 and any Android version.
20
25
  */
21
- export declare const ScreenShareToggleButton: ({ onScreenShareStartedHandler, onScreenShareStoppedHandler, }: ScreenShareToggleButtonProps) => React.JSX.Element | null;
26
+ export declare const ScreenShareToggleButton: ({ onScreenShareStartedHandler, onScreenShareStoppedHandler, screenShareOptions, }: ScreenShareToggleButtonProps) => React.JSX.Element | null;
22
27
  //# sourceMappingURL=ScreenShareToggleButton.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ScreenShareToggleButton.d.ts","sourceRoot":"","sources":["../../../../../src/components/Call/CallControls/ScreenShareToggleButton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAiB,MAAM,OAAO,CAAC;AAUtC;;GAEG;AACH,MAAM,MAAM,4BAA4B,GAAG;IACzC;;;OAGG;IACH,2BAA2B,CAAC,EAAE,MAAM,IAAI,CAAC;IACzC;;;OAGG;IACH,2BAA2B,CAAC,EAAE,MAAM,IAAI,CAAC;CAC1C,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,uBAAuB,GAAI,+DAGrC,4BAA4B,6BA4C9B,CAAC"}
1
+ {"version":3,"file":"ScreenShareToggleButton.d.ts","sourceRoot":"","sources":["../../../../../src/components/Call/CallControls/ScreenShareToggleButton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAiB,MAAM,OAAO,CAAC;AAOtC,OAAO,EAEL,KAAK,kBAAkB,EACxB,MAAM,qCAAqC,CAAC;AAG7C;;GAEG;AACH,MAAM,MAAM,4BAA4B,GAAG;IACzC;;;OAGG;IACH,2BAA2B,CAAC,EAAE,MAAM,IAAI,CAAC;IACzC;;;OAGG;IACH,2BAA2B,CAAC,EAAE,MAAM,IAAI,CAAC;IACzC;;OAEG;IACH,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;CACzC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,uBAAuB,GAAI,mFAIrC,4BAA4B,6BA8C9B,CAAC"}
@@ -6,6 +6,7 @@ export * from './useIsIosScreenshareBroadcastStarted';
6
6
  export * from './useIsInPiPMode';
7
7
  export * from './useAutoEnterPiPEffect';
8
8
  export * from './useScreenShareButton';
9
+ export * from './useScreenShareAudioMixing';
9
10
  export * from './useTrackDimensions';
10
11
  export * from './useScreenshot';
11
12
  export * from './useSpeechDetection';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,QAAQ,CAAC;AACvB,cAAc,iCAAiC,CAAC;AAChD,cAAc,uCAAuC,CAAC;AACtD,cAAc,kBAAkB,CAAC;AACjC,cAAc,yBAAyB,CAAC;AACxC,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,iBAAiB,CAAC;AAChC,cAAc,sBAAsB,CAAC;AACrC,cAAc,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,QAAQ,CAAC;AACvB,cAAc,iCAAiC,CAAC;AAChD,cAAc,uCAAuC,CAAC;AACtD,cAAc,kBAAkB,CAAC;AACjC,cAAc,yBAAyB,CAAC;AACxC,cAAc,wBAAwB,CAAC;AACvC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,sBAAsB,CAAC;AACrC,cAAc,iBAAiB,CAAC;AAChC,cAAc,sBAAsB,CAAC;AACrC,cAAc,iBAAiB,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Hook that manages the lifecycle of screen share audio mixing.
3
+ *
4
+ * When screen share is active and audio mixing is enabled
5
+ * (via `call.screenShare.enableScreenShareAudio()`), this hook
6
+ * calls the native module to mix captured screen/app audio
7
+ * into the microphone audio track.
8
+ *
9
+ * Noise cancellation is temporarily disabled while screen audio mixing
10
+ * is active so that all captured sounds (music, game audio, etc.)
11
+ * pass through without being filtered.
12
+ */
13
+ export declare const useScreenShareAudioMixing: () => void;
14
+ //# sourceMappingURL=useScreenShareAudioMixing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useScreenShareAudioMixing.d.ts","sourceRoot":"","sources":["../../../src/hooks/useScreenShareAudioMixing.ts"],"names":[],"mappings":"AAwCA;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,yBAAyB,YA6ErC,CAAC"}