@stream-io/video-react-native-sdk 1.13.3 → 1.14.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 (124) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/android/gradle.properties +1 -1
  3. package/dist/commonjs/components/Livestream/LivestreamControls/ViewerLeaveStreamButton.js +23 -29
  4. package/dist/commonjs/components/Livestream/LivestreamControls/ViewerLeaveStreamButton.js.map +1 -1
  5. package/dist/commonjs/components/Livestream/LivestreamControls/ViewerLivestreamControls.js +187 -29
  6. package/dist/commonjs/components/Livestream/LivestreamControls/ViewerLivestreamControls.js.map +1 -1
  7. package/dist/commonjs/components/Livestream/LivestreamLayout/LivestreamLayout.js +1 -1
  8. package/dist/commonjs/components/Livestream/LivestreamLayout/LivestreamLayout.js.map +1 -1
  9. package/dist/commonjs/components/Livestream/LivestreamPlayer/LivestreamEnded.js +111 -0
  10. package/dist/commonjs/components/Livestream/LivestreamPlayer/LivestreamEnded.js.map +1 -0
  11. package/dist/commonjs/components/Livestream/LivestreamPlayer/LivestreamPlayer.js +5 -6
  12. package/dist/commonjs/components/Livestream/LivestreamPlayer/LivestreamPlayer.js.map +1 -1
  13. package/dist/commonjs/components/Livestream/LivestreamTopView/DurationBadge.js +32 -28
  14. package/dist/commonjs/components/Livestream/LivestreamTopView/DurationBadge.js.map +1 -1
  15. package/dist/commonjs/components/Livestream/LivestreamTopView/FollowerCount.js +36 -36
  16. package/dist/commonjs/components/Livestream/LivestreamTopView/FollowerCount.js.map +1 -1
  17. package/dist/commonjs/components/Livestream/LivestreamTopView/LiveIndicator.js +21 -15
  18. package/dist/commonjs/components/Livestream/LivestreamTopView/LiveIndicator.js.map +1 -1
  19. package/dist/commonjs/components/Livestream/ViewerLivestream/ViewerLivestream.js +70 -4
  20. package/dist/commonjs/components/Livestream/ViewerLivestream/ViewerLivestream.js.map +1 -1
  21. package/dist/commonjs/components/Livestream/ViewerLivestream/ViewerLobby.js +143 -0
  22. package/dist/commonjs/components/Livestream/ViewerLivestream/ViewerLobby.js.map +1 -0
  23. package/dist/commonjs/icons/LivestreamControls.js +73 -0
  24. package/dist/commonjs/icons/LivestreamControls.js.map +1 -0
  25. package/dist/commonjs/icons/Maximize.js +52 -0
  26. package/dist/commonjs/icons/Maximize.js.map +1 -0
  27. package/dist/commonjs/icons/index.js +11 -0
  28. package/dist/commonjs/icons/index.js.map +1 -1
  29. package/dist/commonjs/index.js +12 -0
  30. package/dist/commonjs/index.js.map +1 -1
  31. package/dist/commonjs/providers/NoiseCancellation/NoiseCancellationProvider.js +75 -0
  32. package/dist/commonjs/providers/NoiseCancellation/NoiseCancellationProvider.js.map +1 -0
  33. package/dist/commonjs/providers/NoiseCancellation/index.js +17 -0
  34. package/dist/commonjs/providers/NoiseCancellation/index.js.map +1 -0
  35. package/dist/commonjs/providers/NoiseCancellation/lib.js +34 -0
  36. package/dist/commonjs/providers/NoiseCancellation/lib.js.map +1 -0
  37. package/dist/commonjs/version.js +1 -1
  38. package/dist/module/components/Livestream/LivestreamControls/ViewerLeaveStreamButton.js +27 -33
  39. package/dist/module/components/Livestream/LivestreamControls/ViewerLeaveStreamButton.js.map +1 -1
  40. package/dist/module/components/Livestream/LivestreamControls/ViewerLivestreamControls.js +187 -30
  41. package/dist/module/components/Livestream/LivestreamControls/ViewerLivestreamControls.js.map +1 -1
  42. package/dist/module/components/Livestream/LivestreamLayout/LivestreamLayout.js +1 -1
  43. package/dist/module/components/Livestream/LivestreamLayout/LivestreamLayout.js.map +1 -1
  44. package/dist/module/components/Livestream/LivestreamPlayer/LivestreamEnded.js +104 -0
  45. package/dist/module/components/Livestream/LivestreamPlayer/LivestreamEnded.js.map +1 -0
  46. package/dist/module/components/Livestream/LivestreamPlayer/LivestreamPlayer.js +5 -6
  47. package/dist/module/components/Livestream/LivestreamPlayer/LivestreamPlayer.js.map +1 -1
  48. package/dist/module/components/Livestream/LivestreamTopView/DurationBadge.js +33 -29
  49. package/dist/module/components/Livestream/LivestreamTopView/DurationBadge.js.map +1 -1
  50. package/dist/module/components/Livestream/LivestreamTopView/FollowerCount.js +35 -35
  51. package/dist/module/components/Livestream/LivestreamTopView/FollowerCount.js.map +1 -1
  52. package/dist/module/components/Livestream/LivestreamTopView/LiveIndicator.js +20 -14
  53. package/dist/module/components/Livestream/LivestreamTopView/LiveIndicator.js.map +1 -1
  54. package/dist/module/components/Livestream/ViewerLivestream/ViewerLivestream.js +73 -7
  55. package/dist/module/components/Livestream/ViewerLivestream/ViewerLivestream.js.map +1 -1
  56. package/dist/module/components/Livestream/ViewerLivestream/ViewerLobby.js +136 -0
  57. package/dist/module/components/Livestream/ViewerLivestream/ViewerLobby.js.map +1 -0
  58. package/dist/module/icons/LivestreamControls.js +62 -0
  59. package/dist/module/icons/LivestreamControls.js.map +1 -0
  60. package/dist/module/icons/Maximize.js +43 -0
  61. package/dist/module/icons/Maximize.js.map +1 -0
  62. package/dist/module/icons/index.js +1 -0
  63. package/dist/module/icons/index.js.map +1 -1
  64. package/dist/module/index.js +1 -0
  65. package/dist/module/index.js.map +1 -1
  66. package/dist/module/providers/NoiseCancellation/NoiseCancellationProvider.js +67 -0
  67. package/dist/module/providers/NoiseCancellation/NoiseCancellationProvider.js.map +1 -0
  68. package/dist/module/providers/NoiseCancellation/index.js +2 -0
  69. package/dist/module/providers/NoiseCancellation/index.js.map +1 -0
  70. package/dist/module/providers/NoiseCancellation/lib.js +26 -0
  71. package/dist/module/providers/NoiseCancellation/lib.js.map +1 -0
  72. package/dist/module/version.js +1 -1
  73. package/dist/typescript/components/Livestream/LivestreamControls/ViewerLeaveStreamButton.d.ts.map +1 -1
  74. package/dist/typescript/components/Livestream/LivestreamControls/ViewerLivestreamControls.d.ts +7 -0
  75. package/dist/typescript/components/Livestream/LivestreamControls/ViewerLivestreamControls.d.ts.map +1 -1
  76. package/dist/typescript/components/Livestream/LivestreamPlayer/LivestreamEnded.d.ts +3 -0
  77. package/dist/typescript/components/Livestream/LivestreamPlayer/LivestreamEnded.d.ts.map +1 -0
  78. package/dist/typescript/components/Livestream/LivestreamPlayer/LivestreamPlayer.d.ts +13 -1
  79. package/dist/typescript/components/Livestream/LivestreamPlayer/LivestreamPlayer.d.ts.map +1 -1
  80. package/dist/typescript/components/Livestream/LivestreamTopView/DurationBadge.d.ts.map +1 -1
  81. package/dist/typescript/components/Livestream/LivestreamTopView/FollowerCount.d.ts.map +1 -1
  82. package/dist/typescript/components/Livestream/LivestreamTopView/LiveIndicator.d.ts.map +1 -1
  83. package/dist/typescript/components/Livestream/ViewerLivestream/ViewerLivestream.d.ts +9 -1
  84. package/dist/typescript/components/Livestream/ViewerLivestream/ViewerLivestream.d.ts.map +1 -1
  85. package/dist/typescript/components/Livestream/ViewerLivestream/ViewerLobby.d.ts +8 -0
  86. package/dist/typescript/components/Livestream/ViewerLivestream/ViewerLobby.d.ts.map +1 -0
  87. package/dist/typescript/icons/LivestreamControls.d.ts +12 -0
  88. package/dist/typescript/icons/LivestreamControls.d.ts.map +1 -0
  89. package/dist/typescript/icons/Maximize.d.ts +10 -0
  90. package/dist/typescript/icons/Maximize.d.ts.map +1 -0
  91. package/dist/typescript/icons/index.d.ts +1 -0
  92. package/dist/typescript/icons/index.d.ts.map +1 -1
  93. package/dist/typescript/index.d.ts +1 -0
  94. package/dist/typescript/index.d.ts.map +1 -1
  95. package/dist/typescript/providers/NoiseCancellation/NoiseCancellationProvider.d.ts +34 -0
  96. package/dist/typescript/providers/NoiseCancellation/NoiseCancellationProvider.d.ts.map +1 -0
  97. package/dist/typescript/providers/NoiseCancellation/index.d.ts +2 -0
  98. package/dist/typescript/providers/NoiseCancellation/index.d.ts.map +1 -0
  99. package/dist/typescript/providers/NoiseCancellation/lib.d.ts +8 -0
  100. package/dist/typescript/providers/NoiseCancellation/lib.d.ts.map +1 -0
  101. package/dist/typescript/version.d.ts +1 -1
  102. package/expo-config-plugin/dist/index.js +2 -0
  103. package/expo-config-plugin/dist/withAndroidPermissions.js +1 -0
  104. package/expo-config-plugin/dist/withAppDelegate.js +26 -7
  105. package/expo-config-plugin/dist/withMainApplication.js +24 -0
  106. package/package.json +10 -5
  107. package/src/components/Livestream/LivestreamControls/ViewerLeaveStreamButton.tsx +30 -48
  108. package/src/components/Livestream/LivestreamControls/ViewerLivestreamControls.tsx +260 -43
  109. package/src/components/Livestream/LivestreamLayout/LivestreamLayout.tsx +1 -1
  110. package/src/components/Livestream/LivestreamPlayer/LivestreamEnded.tsx +130 -0
  111. package/src/components/Livestream/LivestreamPlayer/LivestreamPlayer.tsx +15 -5
  112. package/src/components/Livestream/LivestreamTopView/DurationBadge.tsx +35 -38
  113. package/src/components/Livestream/LivestreamTopView/FollowerCount.tsx +40 -47
  114. package/src/components/Livestream/LivestreamTopView/LiveIndicator.tsx +22 -14
  115. package/src/components/Livestream/ViewerLivestream/ViewerLivestream.tsx +107 -10
  116. package/src/components/Livestream/ViewerLivestream/ViewerLobby.tsx +171 -0
  117. package/src/icons/LivestreamControls.tsx +51 -0
  118. package/src/icons/Maximize.tsx +48 -0
  119. package/src/icons/index.tsx +1 -0
  120. package/src/index.ts +1 -0
  121. package/src/providers/NoiseCancellation/NoiseCancellationProvider.tsx +147 -0
  122. package/src/providers/NoiseCancellation/index.ts +1 -0
  123. package/src/providers/NoiseCancellation/lib.ts +37 -0
  124. package/src/version.ts +1 -1
@@ -0,0 +1,171 @@
1
+ import {
2
+ useCall,
3
+ useCallStateHooks,
4
+ useI18n,
5
+ } from '@stream-io/video-react-bindings';
6
+ import React, { useEffect, useMemo, useState } from 'react';
7
+ import {
8
+ ActivityIndicator,
9
+ Button,
10
+ StyleSheet,
11
+ Text,
12
+ View,
13
+ } from 'react-native';
14
+ import { useTheme } from '../../../contexts';
15
+ import { CallingState } from '@stream-io/video-client';
16
+ import { getLogger } from '@stream-io/video-client';
17
+
18
+ type LobbyProps = {
19
+ isLive: boolean;
20
+ handleJoinCall?: () => void;
21
+ };
22
+
23
+ export const ViewerLobby = ({ isLive }: LobbyProps) => {
24
+ const styles = useStyles();
25
+ const { theme } = useTheme();
26
+ const { t } = useI18n();
27
+ const { useCallStartsAt, useParticipants, useCallCallingState } =
28
+ useCallStateHooks();
29
+ const callingState = useCallCallingState();
30
+ const call = useCall();
31
+ const startsAt = useCallStartsAt();
32
+ const [error, setError] = useState<Error | undefined>(undefined);
33
+ const [countdown, setCountdown] = React.useState(getCountdown(startsAt));
34
+ const participants = useParticipants();
35
+
36
+ useEffect(() => {
37
+ if (!startsAt || isLive) return;
38
+
39
+ const updateCountdown = () => {
40
+ const timeRemaining = Math.max(0, startsAt.getTime() - Date.now());
41
+ if (timeRemaining <= 0) {
42
+ setCountdown('0:00');
43
+ clearInterval(intervalId);
44
+ return;
45
+ }
46
+
47
+ setCountdown(getCountdown(startsAt));
48
+ };
49
+
50
+ updateCountdown();
51
+
52
+ const intervalId = setInterval(updateCountdown, 1000);
53
+
54
+ return () => clearInterval(intervalId);
55
+ }, [startsAt, isLive]);
56
+
57
+ /**
58
+ * Getting the call details is done through `call.get()`.
59
+ * It is essential so that the call is watched and any changes in the call is intercepted.
60
+ */
61
+ useEffect(() => {
62
+ const getCall = async () => {
63
+ if (!call) {
64
+ return;
65
+ }
66
+
67
+ try {
68
+ await call.get();
69
+ } catch (err) {
70
+ if (err instanceof Error) {
71
+ const logger = getLogger(['ViewerLobby']);
72
+ logger('error', 'Error getting call:', err);
73
+ setError(err);
74
+ }
75
+ }
76
+ };
77
+ getCall();
78
+ }, [call]);
79
+
80
+ if (error) {
81
+ return (
82
+ <View style={styles.container}>
83
+ <Text style={styles.text}>
84
+ Error joining the livestream. Please try again later.
85
+ </Text>
86
+ </View>
87
+ );
88
+ }
89
+
90
+ const isJoiningLiveCall = callingState === CallingState.JOINING;
91
+ if (isJoiningLiveCall) {
92
+ return (
93
+ <View style={styles.container}>
94
+ <ActivityIndicator size="large" color={theme.colors.textPrimary} />
95
+ </View>
96
+ );
97
+ }
98
+
99
+ return (
100
+ <View style={styles.container}>
101
+ <Text style={styles.text}>
102
+ {isLive
103
+ ? t('Livestream is still in progress')
104
+ : startsAt
105
+ ? t('Livestream will start in:')
106
+ : t('Livestream will start soon')}
107
+ </Text>
108
+ {startsAt && !isLive && (
109
+ <Text style={styles.countdownText}>{countdown}</Text>
110
+ )}
111
+ {!isLive && participants.length > 0 && (
112
+ <>
113
+ <Text style={styles.participantsText}>
114
+ {`${participants.length} ${t('participants have joined early')}`}
115
+ </Text>
116
+ </>
117
+ )}
118
+ {isLive && (
119
+ <Button title={t('Join Livestream')} onPress={() => call?.join()} />
120
+ )}
121
+ </View>
122
+ );
123
+ };
124
+
125
+ const useStyles = () => {
126
+ const { theme } = useTheme();
127
+ return useMemo(
128
+ () =>
129
+ StyleSheet.create({
130
+ container: {
131
+ flex: 1,
132
+ justifyContent: 'center',
133
+ alignItems: 'center',
134
+ backgroundColor: theme.colors.sheetPrimary,
135
+ padding: theme.variants.spacingSizes.lg,
136
+ },
137
+ text: {
138
+ color: theme.colors.textPrimary,
139
+ fontSize: theme.variants.fontSizes.lg,
140
+ margin: theme.variants.spacingSizes.md,
141
+ textAlign: 'center',
142
+ },
143
+ countdownText: {
144
+ color: theme.colors.textPrimary,
145
+ fontSize: theme.variants.fontSizes.xl,
146
+ fontWeight: 'bold',
147
+ marginBottom: theme.variants.spacingSizes.md,
148
+ textAlign: 'center',
149
+ },
150
+ participantsText: {
151
+ color: theme.colors.textSecondary,
152
+ fontSize: theme.variants.fontSizes.md,
153
+ marginBottom: theme.variants.spacingSizes.sm,
154
+ },
155
+ }),
156
+ [theme],
157
+ );
158
+ };
159
+
160
+ const getCountdown = (startsAt: Date | undefined) => {
161
+ if (!startsAt) {
162
+ return '';
163
+ }
164
+
165
+ const now = Date.now();
166
+ const timeRemaining = Math.max(0, startsAt.getTime() - now);
167
+
168
+ const minutes = Math.floor(timeRemaining / (1000 * 60));
169
+ const seconds = Math.floor((timeRemaining % (1000 * 60)) / 1000);
170
+ return `${minutes}:${seconds.toString().padStart(2, '0')}`;
171
+ };
@@ -0,0 +1,51 @@
1
+ import React from 'react';
2
+ import { Path, Svg } from 'react-native-svg';
3
+ import { ColorValue } from 'react-native/types';
4
+
5
+ type IconProps = {
6
+ color: ColorValue;
7
+ size: number;
8
+ };
9
+
10
+ export const VolumeOn = ({ color, size }: IconProps) => (
11
+ <Svg viewBox="0 0 24 24" width={size} height={size}>
12
+ <Path
13
+ d="M14 5.6v12.8c0 .88-1.04 1.32-1.66.8L7.5 15H5c-.6 0-1-.4-1-1v-4c0-.6.4-1 1-1h2.5l4.84-4.2c.62-.52 1.66-.08 1.66.8z"
14
+ fill={color}
15
+ />
16
+ <Path
17
+ d="M16.5 8.5c1 1 1.5 2.3 1.5 3.5s-.5 2.5-1.5 3.5"
18
+ stroke={color}
19
+ strokeWidth={1.5}
20
+ strokeLinecap="round"
21
+ />
22
+ <Path
23
+ d="M18 6c1.5 1.5 2.5 3.6 2.5 6s-1 4.5-2.5 6"
24
+ stroke={color}
25
+ strokeWidth={1.5}
26
+ strokeLinecap="round"
27
+ />
28
+ </Svg>
29
+ );
30
+
31
+ export const VolumeOff = ({ color, size }: IconProps) => (
32
+ <Svg viewBox="0 0 24 24" width={size} height={size}>
33
+ <Path
34
+ d="M14 5.6v12.8c0 .88-1.04 1.32-1.66.8L7.5 15H5c-.6 0-1-.4-1-1v-4c0-.6.4-1 1-1h2.5l4.84-4.2c.62-.52 1.66-.08 1.66.8z"
35
+ fill={color}
36
+ />
37
+ <Path d="M3 3L21 21" stroke={color} strokeWidth={2} strokeLinecap="round" />
38
+ </Svg>
39
+ );
40
+
41
+ export const PlayIcon = ({ color, size }: IconProps) => (
42
+ <Svg viewBox="0 0 24 24" width={size} height={size}>
43
+ <Path d="M8 5v14l11-7z" fill={color} />
44
+ </Svg>
45
+ );
46
+
47
+ export const PauseIcon = ({ color, size }: IconProps) => (
48
+ <Svg viewBox="0 0 24 24" width={size} height={size}>
49
+ <Path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z" fill={color} />
50
+ </Svg>
51
+ );
@@ -0,0 +1,48 @@
1
+ import React from 'react';
2
+ import { type ColorValue } from 'react-native/types';
3
+ import Svg, { Path } from 'react-native-svg';
4
+
5
+ type IconProps = {
6
+ color: ColorValue;
7
+ width: number;
8
+ height: number;
9
+ };
10
+
11
+ export const Maximize = ({ color, width, height }: IconProps) => {
12
+ return (
13
+ <Svg width={width} height={height} viewBox="0 0 24 24" fill="none">
14
+ <Path
15
+ d="M8 3V5H4V9H2V3H8Z"
16
+ fill={color}
17
+ stroke={color}
18
+ strokeWidth={2}
19
+ strokeLinecap="round"
20
+ strokeLinejoin="round"
21
+ />
22
+ <Path
23
+ d="M16 3H22V9H20V5H16V3Z"
24
+ fill={color}
25
+ stroke={color}
26
+ strokeWidth={2}
27
+ strokeLinecap="round"
28
+ strokeLinejoin="round"
29
+ />
30
+ <Path
31
+ d="M4 15H2V21H8V19H4V15Z"
32
+ fill={color}
33
+ stroke={color}
34
+ strokeWidth={2}
35
+ strokeLinecap="round"
36
+ strokeLinejoin="round"
37
+ />
38
+ <Path
39
+ d="M20 15V19H16V21H22V15H20Z"
40
+ fill={color}
41
+ stroke={color}
42
+ strokeWidth={2}
43
+ strokeLinecap="round"
44
+ strokeLinejoin="round"
45
+ />
46
+ </Svg>
47
+ );
48
+ };
@@ -20,3 +20,4 @@ export * from './StopScreenShare';
20
20
  export * from './EndStreamIcon';
21
21
  export * from './LeaveStreamIcon';
22
22
  export * from './IconWrapper';
23
+ export * from './Maximize';
package/src/index.ts CHANGED
@@ -32,5 +32,6 @@ export * from './translations';
32
32
  // Explicitly re-exporting to resolve ambiguity.
33
33
  export { StreamVideo } from './providers/StreamVideo';
34
34
  export { StreamCall } from './providers/StreamCall';
35
+ export * from './providers/NoiseCancellation';
35
36
 
36
37
  setClientDetails();
@@ -0,0 +1,147 @@
1
+ import React, {
2
+ createContext,
3
+ PropsWithChildren,
4
+ useContext,
5
+ useEffect,
6
+ useState,
7
+ } from 'react';
8
+ import {
9
+ getLogger,
10
+ NoiseCancellationSettingsModeEnum,
11
+ OwnCapability,
12
+ } from '@stream-io/video-client';
13
+
14
+ import { useCall, useCallStateHooks } from '@stream-io/video-react-bindings';
15
+ import {
16
+ getNoiseCancellationLibThrowIfNotInstalled,
17
+ NoiseCancellationWrapper,
18
+ } from './lib';
19
+
20
+ /**
21
+ * The Noise Cancellation API.
22
+ */
23
+ export type NoiseCancellationAPI = {
24
+ /**
25
+ * A boolean providing information whether the device supports advanced audio processing recommended for noise cancellation.
26
+ * This boolean returns `true` if the iOS device supports Apple's Neural Engine or if an Android device has the FEATURE_AUDIO_PROCESSING feature enabled.
27
+ * Devices with this capability are better suited for handling noise cancellation efficiently.
28
+ */
29
+ deviceSupportsAdvancedAudioProcessing: boolean | undefined;
30
+ /**
31
+ * A boolean providing information whether Noise Cancelling functionalities
32
+ * are supported for the current user in call settings.
33
+ */
34
+ isSupported: boolean | undefined;
35
+ /**
36
+ * Provides information whether Noise Cancellation is active or not.
37
+ */
38
+ isEnabled: boolean;
39
+ /**
40
+ * Allows you to enable or disable the Noise Cancellation audio filter.
41
+ *
42
+ * @param enabled a boolean or a setter.
43
+ */
44
+ setEnabled: (enabled: boolean | ((value: boolean) => boolean)) => void;
45
+ };
46
+
47
+ const NoiseCancellationContext = createContext<NoiseCancellationAPI | null>(
48
+ null,
49
+ );
50
+
51
+ /**
52
+ * Exposes the NoiseCancellation API.
53
+ * Throws an error if used outside <NoiseCancellationProvider />.
54
+ */
55
+ export const useNoiseCancellation = (): NoiseCancellationAPI => {
56
+ const context = useContext(NoiseCancellationContext);
57
+ if (!context) {
58
+ throw new Error(
59
+ 'useNoiseCancellation must be used within a NoiseCancellationProvider',
60
+ );
61
+ }
62
+ return context;
63
+ };
64
+
65
+ export const NoiseCancellationProvider = (props: PropsWithChildren<{}>) => {
66
+ const call = useCall();
67
+ const [
68
+ deviceSupportsAdvancedAudioProcessing,
69
+ setDeviceSupportsAdvancedAudioProcessing,
70
+ ] = useState<boolean>();
71
+ const { useCallSettings, useHasPermissions } = useCallStateHooks();
72
+ const settings = useCallSettings();
73
+ const noiseCancellationAllowed = !!(
74
+ settings &&
75
+ settings.audio.noise_cancellation &&
76
+ settings.audio.noise_cancellation.mode !==
77
+ NoiseCancellationSettingsModeEnum.DISABLED
78
+ );
79
+
80
+ const hasCapability = useHasPermissions(
81
+ OwnCapability.ENABLE_NOISE_CANCELLATION,
82
+ );
83
+ const [isEnabled, setIsEnabled] = useState(false);
84
+
85
+ useEffect(() => {
86
+ const noiseCancellationNativeLib =
87
+ getNoiseCancellationLibThrowIfNotInstalled();
88
+ noiseCancellationNativeLib
89
+ .deviceSupportsAdvancedAudioProcessing()
90
+ .then((result) => setDeviceSupportsAdvancedAudioProcessing(result));
91
+ noiseCancellationNativeLib.isEnabled().then((e) => setIsEnabled(e));
92
+ }, []);
93
+
94
+ const isSupported = hasCapability && noiseCancellationAllowed;
95
+
96
+ useEffect(() => {
97
+ if (!call || !isSupported) return;
98
+ const ncInstance = NoiseCancellationWrapper.getInstance();
99
+ const unsubscribe = ncInstance.on('change', (v) => setIsEnabled(v));
100
+ call.microphone
101
+ .enableNoiseCancellation(ncInstance)
102
+ .catch((err) =>
103
+ getLogger(['NoiseCancellationProvider'])(
104
+ 'error',
105
+ `Can't initialize noise suppression`,
106
+ err,
107
+ ),
108
+ );
109
+
110
+ return () => {
111
+ call.microphone
112
+ .disableNoiseCancellation()
113
+ .catch((err) =>
114
+ getLogger(['NoiseCancellationProvider'])(
115
+ 'error',
116
+ `Can't disable noise suppression`,
117
+ err,
118
+ ),
119
+ );
120
+ unsubscribe();
121
+ };
122
+ }, [call, isSupported]);
123
+
124
+ return (
125
+ <NoiseCancellationContext.Provider
126
+ value={{
127
+ deviceSupportsAdvancedAudioProcessing,
128
+ isSupported,
129
+ isEnabled,
130
+ setEnabled: (enabledOrSetter) => {
131
+ const ncInstance = NoiseCancellationWrapper.getInstance();
132
+ const enable =
133
+ typeof enabledOrSetter === 'function'
134
+ ? enabledOrSetter(isEnabled)
135
+ : enabledOrSetter;
136
+ if (enable) {
137
+ ncInstance.enable();
138
+ } else {
139
+ ncInstance.disable();
140
+ }
141
+ },
142
+ }}
143
+ >
144
+ {props.children}
145
+ </NoiseCancellationContext.Provider>
146
+ );
147
+ };
@@ -0,0 +1 @@
1
+ export * from './NoiseCancellationProvider';
@@ -0,0 +1,37 @@
1
+ export type Type = typeof import('@stream-io/noise-cancellation-react-native');
2
+
3
+ let noiseCancellationLib: Type | undefined;
4
+
5
+ try {
6
+ noiseCancellationLib = require('@stream-io/noise-cancellation-react-native');
7
+ } catch {}
8
+
9
+ export function getNoiseCancellationLibThrowIfNotInstalled() {
10
+ if (!noiseCancellationLib) {
11
+ throw Error(
12
+ '@stream-io/noise-cancellation-react-native is not installed. It is required for implementing noise cancellation. ',
13
+ );
14
+ }
15
+ return noiseCancellationLib;
16
+ }
17
+
18
+ export class NoiseCancellationWrapper {
19
+ private static noiseCancellationInstance:
20
+ | InstanceType<Type['NoiseCancellation']>
21
+ | undefined;
22
+
23
+ private constructor() {}
24
+
25
+ static getInstance(): InstanceType<Type['NoiseCancellation']> {
26
+ if (!this.noiseCancellationInstance) {
27
+ const ncLib = getNoiseCancellationLibThrowIfNotInstalled();
28
+ this.noiseCancellationInstance = new ncLib.NoiseCancellation();
29
+ }
30
+ return this.noiseCancellationInstance;
31
+ }
32
+ }
33
+
34
+ /*
35
+ IMPORTANT: must keep a failing import in a different file
36
+ Else on commonjs, metro doesnt resolve any other modules properly in a file, if one of the module is not installed
37
+ */
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const version = '1.13.3';
1
+ export const version = '1.14.0';