@stream-io/video-react-native-sdk 1.0.0-rc2.0 → 1.0.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 (93) hide show
  1. package/CHANGELOG.md +14 -83
  2. package/dist/commonjs/components/Call/CallContent/CallContent.js +10 -5
  3. package/dist/commonjs/components/Call/CallContent/CallContent.js.map +1 -1
  4. package/dist/commonjs/components/Call/CallContent/RTCViewPipIOS.js +109 -0
  5. package/dist/commonjs/components/Call/CallContent/RTCViewPipIOS.js.map +1 -0
  6. package/dist/commonjs/components/Call/CallContent/index.js +11 -0
  7. package/dist/commonjs/components/Call/CallContent/index.js.map +1 -1
  8. package/dist/commonjs/components/Call/CallLayout/CallParticipantsGrid.js +4 -3
  9. package/dist/commonjs/components/Call/CallLayout/CallParticipantsGrid.js.map +1 -1
  10. package/dist/commonjs/components/Call/CallLayout/CallParticipantsSpotlight.js +4 -3
  11. package/dist/commonjs/components/Call/CallLayout/CallParticipantsSpotlight.js.map +1 -1
  12. package/dist/commonjs/hooks/useAutoEnterPiPEffect.js +3 -3
  13. package/dist/commonjs/hooks/useAutoEnterPiPEffect.js.map +1 -1
  14. package/dist/commonjs/hooks/useIsInPiPMode.js +4 -4
  15. package/dist/commonjs/hooks/useIsInPiPMode.js.map +1 -1
  16. package/dist/commonjs/providers/StreamCall.js +5 -2
  17. package/dist/commonjs/providers/StreamCall.js.map +1 -1
  18. package/dist/commonjs/utils/internal/shouldDisableIOSLocalVideoOnBackground.js +10 -0
  19. package/dist/commonjs/utils/internal/shouldDisableIOSLocalVideoOnBackground.js.map +1 -0
  20. package/dist/commonjs/version.js +1 -1
  21. package/dist/commonjs/version.js.map +1 -1
  22. package/dist/module/components/Call/CallContent/CallContent.js +10 -5
  23. package/dist/module/components/Call/CallContent/CallContent.js.map +1 -1
  24. package/dist/module/components/Call/CallContent/RTCViewPipIOS.js +101 -0
  25. package/dist/module/components/Call/CallContent/RTCViewPipIOS.js.map +1 -0
  26. package/dist/module/components/Call/CallContent/index.js +1 -0
  27. package/dist/module/components/Call/CallContent/index.js.map +1 -1
  28. package/dist/module/components/Call/CallLayout/CallParticipantsGrid.js +4 -3
  29. package/dist/module/components/Call/CallLayout/CallParticipantsGrid.js.map +1 -1
  30. package/dist/module/components/Call/CallLayout/CallParticipantsSpotlight.js +4 -3
  31. package/dist/module/components/Call/CallLayout/CallParticipantsSpotlight.js.map +1 -1
  32. package/dist/module/hooks/useAutoEnterPiPEffect.js +3 -3
  33. package/dist/module/hooks/useAutoEnterPiPEffect.js.map +1 -1
  34. package/dist/module/hooks/useIsInPiPMode.js +4 -4
  35. package/dist/module/hooks/useIsInPiPMode.js.map +1 -1
  36. package/dist/module/providers/StreamCall.js +5 -2
  37. package/dist/module/providers/StreamCall.js.map +1 -1
  38. package/dist/module/utils/internal/shouldDisableIOSLocalVideoOnBackground.js +4 -0
  39. package/dist/module/utils/internal/shouldDisableIOSLocalVideoOnBackground.js.map +1 -0
  40. package/dist/module/version.js +1 -1
  41. package/dist/module/version.js.map +1 -1
  42. package/dist/typescript/components/Call/CallContent/CallContent.d.ts +6 -1
  43. package/dist/typescript/components/Call/CallContent/CallContent.d.ts.map +1 -1
  44. package/dist/typescript/components/Call/CallContent/RTCViewPipIOS.d.ts +7 -0
  45. package/dist/typescript/components/Call/CallContent/RTCViewPipIOS.d.ts.map +1 -0
  46. package/dist/typescript/components/Call/CallContent/index.d.ts +1 -0
  47. package/dist/typescript/components/Call/CallContent/index.d.ts.map +1 -1
  48. package/dist/typescript/components/Call/CallLayout/CallParticipantsGrid.d.ts +2 -2
  49. package/dist/typescript/components/Call/CallLayout/CallParticipantsGrid.d.ts.map +1 -1
  50. package/dist/typescript/components/Call/CallLayout/CallParticipantsSpotlight.d.ts +2 -2
  51. package/dist/typescript/components/Call/CallLayout/CallParticipantsSpotlight.d.ts.map +1 -1
  52. package/dist/typescript/hooks/useAutoEnterPiPEffect.d.ts +1 -1
  53. package/dist/typescript/hooks/useAutoEnterPiPEffect.d.ts.map +1 -1
  54. package/dist/typescript/hooks/useIsInPiPMode.d.ts +1 -1
  55. package/dist/typescript/hooks/useIsInPiPMode.d.ts.map +1 -1
  56. package/dist/typescript/providers/StreamCall.d.ts.map +1 -1
  57. package/dist/typescript/utils/internal/shouldDisableIOSLocalVideoOnBackground.d.ts +4 -0
  58. package/dist/typescript/utils/internal/shouldDisableIOSLocalVideoOnBackground.d.ts.map +1 -0
  59. package/dist/typescript/version.d.ts +1 -1
  60. package/dist/typescript/version.d.ts.map +1 -1
  61. package/ios/PictureInPicture/SampleBufferVideoCallView.swift +52 -0
  62. package/ios/PictureInPicture/StreamAVPictureInPictureVideoCallViewController.swift +83 -0
  63. package/ios/PictureInPicture/StreamBufferTransformer.swift +96 -0
  64. package/ios/PictureInPicture/StreamPictureInPictureController.swift +185 -0
  65. package/ios/PictureInPicture/StreamPictureInPictureTrackStateAdapter.swift +68 -0
  66. package/ios/PictureInPicture/StreamPictureInPictureVideoRenderer.swift +250 -0
  67. package/ios/PictureInPicture/StreamPixelBufferPool.swift +118 -0
  68. package/ios/PictureInPicture/StreamPixelBufferRepository.swift +98 -0
  69. package/ios/PictureInPicture/StreamRTCYUVBuffer.swift +249 -0
  70. package/ios/PictureInPicture/StreamYUVToARGBConversion.swift +128 -0
  71. package/ios/PictureInPicture/WindowSizePolicy/StreamPictureInPictureAdaptiveWindowSizePolicy.swift +25 -0
  72. package/ios/PictureInPicture/WindowSizePolicy/StreamPictureInPictureFixedWindowSizePolicy.swift +29 -0
  73. package/ios/PictureInPicture/WindowSizePolicy/StreamPictureInPictureWindowSizePolicy.swift +14 -0
  74. package/ios/PictureInPicture/YpCbCrPixelRange+Default.swift +32 -0
  75. package/ios/RTCViewPip.swift +69 -0
  76. package/ios/RTCViewPipManager.mm +16 -0
  77. package/ios/RTCViewPipManager.swift +34 -0
  78. package/ios/StreamVideoReactNative-Bridging-Header.h +11 -0
  79. package/package.json +4 -4
  80. package/src/components/Call/CallContent/CallContent.tsx +58 -40
  81. package/src/components/Call/CallContent/RTCViewPipIOS.tsx +138 -0
  82. package/src/components/Call/CallContent/index.ts +1 -0
  83. package/src/components/Call/CallLayout/CallParticipantsGrid.tsx +7 -3
  84. package/src/components/Call/CallLayout/CallParticipantsSpotlight.tsx +7 -3
  85. package/src/hooks/useAutoEnterPiPEffect.tsx +7 -3
  86. package/src/hooks/useIsInPiPMode.tsx +6 -4
  87. package/src/providers/StreamCall.tsx +5 -2
  88. package/src/utils/internal/shouldDisableIOSLocalVideoOnBackground.ts +3 -0
  89. package/src/version.ts +1 -1
  90. package/stream-video-react-native.podspec +27 -4
  91. package/ios/StreamVideoReactNative.xcodeproj/project.pbxproj +0 -274
  92. package/ios/StreamVideoReactNative.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -7
  93. package/ios/StreamVideoReactNative.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -8
@@ -37,6 +37,7 @@ import {
37
37
  ScreenShareOverlay as DefaultScreenShareOverlay,
38
38
  ScreenShareOverlayProps,
39
39
  } from '../../utility/ScreenShareOverlay';
40
+ import RTCViewPipIOS from './RTCViewPipIOS';
40
41
 
41
42
  export type StreamReactionType = StreamReaction & {
42
43
  icon: string;
@@ -88,6 +89,14 @@ export type CallContentProps = Pick<
88
89
  * This will apply the landscape mode styles to the component.
89
90
  */
90
91
  landscape?: boolean;
92
+ /*
93
+ * If true, includes the local participant video in the PiP mode for iOS
94
+ */
95
+ iOSPiPIncludeLocalParticipantVideo?: boolean;
96
+ /**
97
+ * If true, disables the Picture-in-Picture mode for iOS and Android
98
+ */
99
+ disablePictureInPicture?: boolean;
91
100
  };
92
101
 
93
102
  export const CallContent = ({
@@ -109,6 +118,8 @@ export const CallContent = ({
109
118
  layout = 'grid',
110
119
  landscape = false,
111
120
  supportedReactions,
121
+ iOSPiPIncludeLocalParticipantVideo,
122
+ disablePictureInPicture,
112
123
  }: CallContentProps) => {
113
124
  const [
114
125
  showRemoteParticipantInFloatingView,
@@ -124,7 +135,7 @@ export const CallContent = ({
124
135
  useLocalParticipant,
125
136
  } = useCallStateHooks();
126
137
 
127
- useAutoEnterPiPEffect();
138
+ useAutoEnterPiPEffect(disablePictureInPicture);
128
139
 
129
140
  const callSettings = useCallSettings();
130
141
  const isVideoEnabledInCall = callSettings?.video.enabled;
@@ -132,7 +143,7 @@ export const CallContent = ({
132
143
  const _remoteParticipants = useRemoteParticipants();
133
144
  const remoteParticipants = useDebouncedValue(_remoteParticipants, 300); // we debounce the remote participants to avoid unnecessary rerenders that happen when participant tracks are all subscribed simultaneously
134
145
  const localParticipant = useLocalParticipant();
135
- const isInPiPMode = useIsInPiPMode();
146
+ const isInPiPMode = useIsInPiPMode(disablePictureInPicture);
136
147
  const hasScreenShare = useHasOngoingScreenShare();
137
148
  const showSpotlightLayout = hasScreenShare || layout === 'spotlight';
138
149
 
@@ -195,48 +206,55 @@ export const CallContent = ({
195
206
  };
196
207
 
197
208
  return (
198
- <View style={[styles.container, landscapeStyles, callContent.container]}>
199
- <View style={[styles.container, callContent.callParticipantsContainer]}>
200
- <View
201
- style={[styles.view, callContent.topContainer]}
202
- // "box-none" disallows the container view to be not take up touches
203
- // and allows only the top and floating view (its child views) to take up the touches
204
- pointerEvents="box-none"
205
- >
206
- {!isInPiPMode && CallTopView && (
207
- <CallTopView
208
- onBackPressed={onBackPressed}
209
- onParticipantInfoPress={onParticipantInfoPress}
210
- ParticipantsInfoBadge={ParticipantsInfoBadge}
211
- />
212
- )}
213
- {showFloatingView && FloatingParticipantView && (
214
- <FloatingParticipantView
215
- participant={
216
- isRemoteParticipantInFloatingView
217
- ? remoteParticipants[0]
218
- : localParticipant
219
- }
220
- onPressHandler={handleFloatingViewParticipantSwitch}
221
- supportedReactions={supportedReactions}
222
- {...participantViewProps}
223
- />
209
+ <>
210
+ {!disablePictureInPicture && (
211
+ <RTCViewPipIOS
212
+ includeLocalParticipantVideo={iOSPiPIncludeLocalParticipantVideo}
213
+ />
214
+ )}
215
+ <View style={[styles.container, landscapeStyles, callContent.container]}>
216
+ <View style={[styles.container, callContent.callParticipantsContainer]}>
217
+ <View
218
+ style={[styles.view, callContent.topContainer]}
219
+ // "box-none" disallows the container view to be not take up touches
220
+ // and allows only the top and floating view (its child views) to take up the touches
221
+ pointerEvents="box-none"
222
+ >
223
+ {!isInPiPMode && CallTopView && (
224
+ <CallTopView
225
+ onBackPressed={onBackPressed}
226
+ onParticipantInfoPress={onParticipantInfoPress}
227
+ ParticipantsInfoBadge={ParticipantsInfoBadge}
228
+ />
229
+ )}
230
+ {showFloatingView && FloatingParticipantView && (
231
+ <FloatingParticipantView
232
+ participant={
233
+ isRemoteParticipantInFloatingView
234
+ ? remoteParticipants[0]
235
+ : localParticipant
236
+ }
237
+ onPressHandler={handleFloatingViewParticipantSwitch}
238
+ supportedReactions={supportedReactions}
239
+ {...participantViewProps}
240
+ />
241
+ )}
242
+ </View>
243
+ {showSpotlightLayout ? (
244
+ <CallParticipantsSpotlight {...callParticipantsSpotlightProps} />
245
+ ) : (
246
+ <CallParticipantsGrid {...callParticipantsGridProps} />
224
247
  )}
225
248
  </View>
226
- {showSpotlightLayout ? (
227
- <CallParticipantsSpotlight {...callParticipantsSpotlightProps} />
228
- ) : (
229
- <CallParticipantsGrid {...callParticipantsGridProps} />
249
+
250
+ {!isInPiPMode && CallControls && (
251
+ <CallControls
252
+ onHangupCallHandler={onHangupCallHandler}
253
+ landscape={landscape}
254
+ />
230
255
  )}
231
256
  </View>
232
-
233
- {!isInPiPMode && CallControls && (
234
- <CallControls
235
- onHangupCallHandler={onHangupCallHandler}
236
- landscape={landscape}
237
- />
238
- )}
239
- </View>
257
+ </>
240
258
  );
241
259
  };
242
260
 
@@ -0,0 +1,138 @@
1
+ import {
2
+ CallingState,
3
+ hasScreenShare,
4
+ speakerLayoutSortPreset,
5
+ } from '@stream-io/video-client';
6
+ import { useCall, useCallStateHooks } from '@stream-io/video-react-bindings';
7
+ import type { MediaStream } from '@stream-io/react-native-webrtc';
8
+ import React, { useEffect } from 'react';
9
+ import {
10
+ findNodeHandle,
11
+ HostComponent,
12
+ Platform,
13
+ requireNativeComponent,
14
+ UIManager,
15
+ } from 'react-native';
16
+ import { useDebouncedValue } from '../../../utils/hooks/useDebouncedValue';
17
+ import { shouldDisableIOSLocalVideoOnBackgroundRef } from '../../../utils/internal/shouldDisableIOSLocalVideoOnBackground';
18
+
19
+ const COMPONENT_NAME = 'RTCViewPip';
20
+
21
+ type RTCViewPipNativeProps = {
22
+ streamURL?: string;
23
+ };
24
+
25
+ // workaround to support hot reloading
26
+ // https://medium.com/tribalscale/beyond-the-framework-using-react-native-with-swift-and-kotlin-cfccf4bb9a03
27
+ let RTCViewPipNative: HostComponent<RTCViewPipNativeProps>;
28
+
29
+ if (__DEV__) {
30
+ /* @ts-ignore */
31
+ const cachedView = global.RTCViewPipNative as
32
+ | HostComponent<RTCViewPipNativeProps>
33
+ | undefined;
34
+ if (!cachedView) {
35
+ RTCViewPipNative = requireNativeComponent(COMPONENT_NAME);
36
+ /* @ts-ignore */
37
+ global.RTCViewPipNative = RTCViewPipNative;
38
+ } else {
39
+ RTCViewPipNative = cachedView;
40
+ }
41
+ } else {
42
+ RTCViewPipNative = requireNativeComponent(COMPONENT_NAME);
43
+ }
44
+
45
+ /** Wrapper for the native view
46
+ * meant to stay private and not exposed */
47
+ const RTCViewPip = React.forwardRef<
48
+ React.Ref<any>,
49
+ {
50
+ streamURL?: string;
51
+ }
52
+ >((props, ref) => {
53
+ if (Platform.OS !== 'ios') return null;
54
+ // @ts-ignore
55
+ return <RTCViewPipNative streamURL={props.streamURL} ref={ref} />;
56
+ });
57
+
58
+ type Props = {
59
+ includeLocalParticipantVideo?: boolean;
60
+ };
61
+
62
+ const RTCViewPipIOS = ({ includeLocalParticipantVideo }: Props) => {
63
+ const call = useCall();
64
+ const { useParticipants } = useCallStateHooks();
65
+ const _allParticipants = useParticipants({
66
+ sortBy: speakerLayoutSortPreset,
67
+ });
68
+ const allParticipants = useDebouncedValue(_allParticipants, 300); // we debounce the participants to avoid unnecessary rerenders that happen when participant tracks are all subscribed simultaneously
69
+
70
+ const [participantInSpotlight] = allParticipants.filter((participant) =>
71
+ includeLocalParticipantVideo ? true : !participant.isLocalParticipant
72
+ );
73
+
74
+ useEffect(() => {
75
+ shouldDisableIOSLocalVideoOnBackgroundRef.current =
76
+ !includeLocalParticipantVideo;
77
+ }, [includeLocalParticipantVideo]);
78
+
79
+ const [videoStreamToRender, setVideoStreamToRender] =
80
+ React.useState<MediaStream>();
81
+
82
+ const nativeRef = React.useRef<any>(null);
83
+
84
+ React.useEffect(() => {
85
+ if (!participantInSpotlight) {
86
+ setVideoStreamToRender(undefined);
87
+ return;
88
+ }
89
+ const { videoStream, screenShareStream } = participantInSpotlight;
90
+
91
+ const isScreenSharing = hasScreenShare(participantInSpotlight);
92
+
93
+ const _videoStreamToRender = (isScreenSharing
94
+ ? screenShareStream
95
+ : videoStream) as unknown as MediaStream | undefined;
96
+
97
+ setVideoStreamToRender(_videoStreamToRender);
98
+ }, [participantInSpotlight]);
99
+
100
+ React.useEffect(() => {
101
+ let callClosedInvokedOnce = false;
102
+ const onCallClosed = () => {
103
+ if (callClosedInvokedOnce) {
104
+ return;
105
+ }
106
+ callClosedInvokedOnce = true;
107
+ const node = findNodeHandle(nativeRef.current);
108
+ if (node !== null) {
109
+ UIManager.dispatchViewManagerCommand(
110
+ node,
111
+ // @ts-ignore
112
+ UIManager.getViewManagerConfig(COMPONENT_NAME).Commands.onCallClosed,
113
+ []
114
+ );
115
+ }
116
+ shouldDisableIOSLocalVideoOnBackgroundRef.current = true;
117
+ };
118
+ const unsubFunc = call?.on('call.ended', () => {
119
+ onCallClosed();
120
+ });
121
+ const subscription = call?.state.callingState$.subscribe((state) => {
122
+ if (state === CallingState.LEFT || state === CallingState.IDLE) {
123
+ onCallClosed();
124
+ }
125
+ });
126
+ return () => {
127
+ onCallClosed();
128
+ unsubFunc?.();
129
+ subscription?.unsubscribe();
130
+ };
131
+ }, [call]);
132
+
133
+ return (
134
+ <RTCViewPip streamURL={videoStreamToRender?.toURL()} ref={nativeRef} />
135
+ );
136
+ };
137
+
138
+ export default RTCViewPipIOS;
@@ -1 +1,2 @@
1
1
  export * from './CallContent';
2
+ export * from './RTCViewPipIOS';
@@ -10,14 +10,17 @@ import { ComponentTestIds } from '../../../constants/TestIds';
10
10
  import { useTheme } from '../../../contexts/ThemeContext';
11
11
  import { CallContentProps } from '../CallContent';
12
12
  import { ParticipantViewComponentProps } from '../../Participant';
13
- import { useIsInPiPMode } from '../../../hooks';
13
+ import { useIsInPiPMode } from '../../../hooks/useIsInPiPMode';
14
14
  import { StreamVideoParticipant } from '@stream-io/video-client';
15
15
 
16
16
  /**
17
17
  * Props for the CallParticipantsGrid component.
18
18
  */
19
19
  export type CallParticipantsGridProps = ParticipantViewComponentProps &
20
- Pick<CallContentProps, 'supportedReactions' | 'CallParticipantsList'> &
20
+ Pick<
21
+ CallContentProps,
22
+ 'supportedReactions' | 'CallParticipantsList' | 'disablePictureInPicture'
23
+ > &
21
24
  Pick<CallParticipantsListComponentProps, 'ParticipantView'> & {
22
25
  /**
23
26
  * Boolean to decide if local participant will be visible in the grid when there is 1:1 call.
@@ -44,6 +47,7 @@ export const CallParticipantsGrid = ({
44
47
  showLocalParticipant = false,
45
48
  supportedReactions,
46
49
  landscape,
50
+ disablePictureInPicture,
47
51
  }: CallParticipantsGridProps) => {
48
52
  const {
49
53
  theme: { colors, callParticipantsGrid },
@@ -60,7 +64,7 @@ export const CallParticipantsGrid = ({
60
64
  flexDirection: landscape ? 'row' : 'column',
61
65
  };
62
66
 
63
- const isInPiPMode = useIsInPiPMode();
67
+ const isInPiPMode = useIsInPiPMode(disablePictureInPicture);
64
68
 
65
69
  const showFloatingView =
66
70
  !isInPiPMode &&
@@ -17,7 +17,7 @@ import {
17
17
  } from '../../Participant';
18
18
  import { useTheme } from '../../../contexts/ThemeContext';
19
19
  import { CallContentProps } from '../CallContent';
20
- import { useIsInPiPMode } from '../../../hooks';
20
+ import { useIsInPiPMode } from '../../../hooks/useIsInPiPMode';
21
21
 
22
22
  /**
23
23
  * Props for the CallParticipantsSpotlight component.
@@ -25,7 +25,10 @@ import { useIsInPiPMode } from '../../../hooks';
25
25
  export type CallParticipantsSpotlightProps = ParticipantViewComponentProps &
26
26
  Pick<
27
27
  CallContentProps,
28
- 'supportedReactions' | 'CallParticipantsList' | 'ScreenShareOverlay'
28
+ | 'supportedReactions'
29
+ | 'CallParticipantsList'
30
+ | 'ScreenShareOverlay'
31
+ | 'disablePictureInPicture'
29
32
  > &
30
33
  Pick<CallParticipantsListComponentProps, 'ParticipantView'> & {
31
34
  /**
@@ -50,6 +53,7 @@ export const CallParticipantsSpotlight = ({
50
53
  VideoRenderer,
51
54
  supportedReactions,
52
55
  landscape,
56
+ disablePictureInPicture,
53
57
  }: CallParticipantsSpotlightProps) => {
54
58
  const {
55
59
  theme: { colors, callParticipantsSpotlight },
@@ -64,7 +68,7 @@ export const CallParticipantsSpotlight = ({
64
68
  participantInSpotlight && hasScreenShare(participantInSpotlight);
65
69
  const isUserAloneInCall = _allParticipants?.length === 1;
66
70
 
67
- const isInPiP = useIsInPiPMode();
71
+ const isInPiP = useIsInPiPMode(disablePictureInPicture);
68
72
 
69
73
  const participantViewProps: ParticipantViewComponentProps = {
70
74
  ParticipantLabel,
@@ -1,16 +1,20 @@
1
1
  import { useEffect } from 'react';
2
2
  import { NativeModules, Platform } from 'react-native';
3
3
 
4
- export function useAutoEnterPiPEffect() {
4
+ export function useAutoEnterPiPEffect(
5
+ disablePictureInPicture: boolean | undefined
6
+ ) {
5
7
  useEffect(() => {
6
8
  if (Platform.OS !== 'android') {
7
9
  return;
8
10
  }
9
11
 
10
- NativeModules.StreamVideoReactNative.canAutoEnterPipMode(true);
12
+ NativeModules.StreamVideoReactNative.canAutoEnterPipMode(
13
+ !disablePictureInPicture
14
+ );
11
15
 
12
16
  return () => {
13
17
  NativeModules.StreamVideoReactNative.canAutoEnterPipMode(false);
14
18
  };
15
- }, []);
19
+ }, [disablePictureInPicture]);
16
20
  }
@@ -10,9 +10,11 @@ const PIP_CHANGE_EVENT = 'StreamVideoReactNative_PIP_CHANGE_EVENT';
10
10
 
11
11
  const isAndroid8OrAbove = Platform.OS === 'android' && Platform.Version >= 26;
12
12
 
13
- export function useIsInPiPMode() {
13
+ export function useIsInPiPMode(disablePictureInPicture: boolean | undefined) {
14
14
  const [isInPiPMode, setIsInPiPMode] = useState(
15
- isAndroid8OrAbove && AppState.currentState === 'background'
15
+ disablePictureInPicture &&
16
+ isAndroid8OrAbove &&
17
+ AppState.currentState === 'background'
16
18
  );
17
19
 
18
20
  useEffect(() => {
@@ -39,7 +41,7 @@ export function useIsInPiPMode() {
39
41
  'change',
40
42
  (nextAppState) => {
41
43
  if (nextAppState === 'background') {
42
- setIsInPiPMode(true); // set with an assumption that its enabled so that UI disabling happens faster
44
+ setIsInPiPMode(!disablePictureInPicture); // set with an assumption that its enabled so that UI disabling happens faster
43
45
  // if PiP was not enabled anyway, then in the next code we ll set it to false and UI wont be shown anyway
44
46
  }
45
47
  setFromNativeMethod();
@@ -52,7 +54,7 @@ export function useIsInPiPMode() {
52
54
  subscriptionPiPChange.remove();
53
55
  subscriptionAppState.remove();
54
56
  };
55
- }, []);
57
+ }, [disablePictureInPicture]);
56
58
 
57
59
  return isInPiPMode;
58
60
  }
@@ -8,6 +8,7 @@ import {
8
8
  } from '../utils/push/utils';
9
9
  import { useAndroidKeepCallAliveEffect } from '../hooks/useAndroidKeepCallAliveEffect';
10
10
  import { AppState, NativeModules, Platform } from 'react-native';
11
+ import { shouldDisableIOSLocalVideoOnBackgroundRef } from '../utils/internal/shouldDisableIOSLocalVideoOnBackground';
11
12
 
12
13
  export type StreamCallProps = {
13
14
  /**
@@ -77,7 +78,9 @@ const AppStateListener = () => {
77
78
  }
78
79
  );
79
80
  } else {
80
- call?.camera?.disable();
81
+ if (shouldDisableIOSLocalVideoOnBackgroundRef.current) {
82
+ call?.camera?.disable();
83
+ }
81
84
  }
82
85
  appState.current = nextAppState;
83
86
  }
@@ -92,7 +95,7 @@ const AppStateListener = () => {
92
95
  };
93
96
 
94
97
  /**
95
- * This is a renderless component is used to keep the call alive on Android device using useAndroidKeepCallAliveEffect.
98
+ * This is a renderless component to keep the call alive on Android device using useAndroidKeepCallAliveEffect.
96
99
  * useAndroidKeepCallAliveEffect needs to called inside a child of StreamCallProvider.
97
100
  */
98
101
  const AndroidKeepCallAlive = () => {
@@ -0,0 +1,3 @@
1
+ export const shouldDisableIOSLocalVideoOnBackgroundRef = {
2
+ current: true,
3
+ };
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const version = '1.0.0-rc2.0';
1
+ export const version = '1.0.1';
@@ -1,6 +1,7 @@
1
1
  require "json"
2
2
 
3
3
  package = JSON.parse(File.read(File.join(__dir__, "package.json")))
4
+ folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32'
4
5
 
5
6
  Pod::Spec.new do |s|
6
7
  s.name = "stream-video-react-native"
@@ -10,11 +11,33 @@ Pod::Spec.new do |s|
10
11
  s.license = package["license"]
11
12
  s.authors = package["author"]
12
13
 
13
- s.platforms = { :ios => "10.0" }
14
+ s.platforms = { :ios => (min_ios_version_supported || '12.0') }
14
15
  s.source = { :git => "https://github.com/GetStream/stream-video-js/tree/main/packages/react-native-sdk.git", :tag => "#{s.version}" }
15
16
 
16
- s.source_files = "ios/**/*.{h,m,mm}"
17
-
18
- s.dependency "React-Core"
17
+ s.source_files = "ios/**/*.{h,m,mm,swift}"
19
18
  s.dependency "stream-react-native-webrtc"
19
+
20
+ # Use install_modules_dependencies helper to install the dependencies if React Native version >=0.71.0.
21
+ # See https://github.com/facebook/react-native/blob/febf6b7f33fdb4904669f99d795eba4c0f95d7bf/scripts/cocoapods/new_architecture.rb#L79.
22
+ if respond_to?(:install_modules_dependencies, true)
23
+ install_modules_dependencies(s)
24
+ else
25
+ s.dependency "React-Core"
26
+
27
+ # Don't install the dependencies when we run `pod install` in the old architecture.
28
+ if ENV['RCT_NEW_ARCH_ENABLED'] == '1' then
29
+ s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1"
30
+ s.pod_target_xcconfig = {
31
+ "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"",
32
+ "OTHER_CPLUSPLUSFLAGS" => "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1",
33
+ "CLANG_CXX_LANGUAGE_STANDARD" => "c++17"
34
+ }
35
+ s.dependency "React-RCTFabric"
36
+ s.dependency "React-Codegen"
37
+ s.dependency "RCT-Folly"
38
+ s.dependency "RCTRequired"
39
+ s.dependency "RCTTypeSafety"
40
+ s.dependency "ReactCommon/turbomodule/core"
41
+ end
42
+ end
20
43
  end