stream-chat-react-native 5.28.1 → 5.29.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.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "stream-chat-react-native",
3
3
  "description": "The official React Native SDK for Stream Chat, a service for building chat applications",
4
- "version": "5.28.1",
4
+ "version": "5.29.0",
5
5
  "author": {
6
6
  "company": "Stream.io Inc",
7
7
  "name": "Stream.io Inc"
@@ -11,7 +11,7 @@
11
11
  "types": "types/index.d.ts",
12
12
  "dependencies": {
13
13
  "es6-symbol": "^3.1.3",
14
- "stream-chat-react-native-core": "5.28.1"
14
+ "stream-chat-react-native-core": "5.29.0"
15
15
  },
16
16
  "peerDependencies": {
17
17
  "@react-native-camera-roll/camera-roll": ">=5.0.0",
@@ -25,6 +25,7 @@
25
25
  "react-native-image-crop-picker": ">=0.33.2",
26
26
  "react-native-image-resizer": ">=1.4.2",
27
27
  "react-native-share": ">=4.1.0",
28
+ "react-native-audio-recorder-player": ">=3.6.4",
28
29
  "react-native-video": ">=5.2.1"
29
30
  },
30
31
  "peerDependenciesMeta": {
@@ -40,6 +41,9 @@
40
41
  "react-native-haptic-feedback": {
41
42
  "optional": true
42
43
  },
44
+ "react-native-audio-recorder-player": {
45
+ "optional": true
46
+ },
43
47
  "react-native-video": {
44
48
  "optional": true
45
49
  }
@@ -6,7 +6,7 @@ export const Sound = {
6
6
  initializeSound: null,
7
7
  // eslint-disable-next-line react/display-name
8
8
  Player: AudioVideoPlayer
9
- ? ({ onBuffer, onEnd, onLoad, onProgress, paused, soundRef, style, uri }) => (
9
+ ? ({ onBuffer, onEnd, onLoad, onProgress, paused, rate, soundRef, style, uri }) => (
10
10
  <AudioVideoPlayer
11
11
  audioOnly={true}
12
12
  onBuffer={onBuffer}
@@ -17,6 +17,7 @@ export const Sound = {
17
17
  onLoad={onLoad}
18
18
  onProgress={onProgress}
19
19
  paused={paused}
20
+ rate={rate}
20
21
  ref={soundRef}
21
22
  source={{
22
23
  uri,
package/src/index.js CHANGED
@@ -18,6 +18,7 @@ import {
18
18
  } from './handlers';
19
19
 
20
20
  import {
21
+ Audio,
21
22
  pickDocument,
22
23
  setClipboardString,
23
24
  shareImage,
@@ -25,6 +26,7 @@ import {
25
26
  } from './optionalDependencies';
26
27
 
27
28
  registerNativeHandlers({
29
+ Audio,
28
30
  compressImage,
29
31
  deleteFile,
30
32
  FlatList,
@@ -0,0 +1,243 @@
1
+ import { PermissionsAndroid, Platform } from 'react-native';
2
+ import RNFS from 'react-native-fs';
3
+ let AudioRecorderPackage;
4
+ let audioRecorderPlayer;
5
+
6
+ try {
7
+ AudioRecorderPackage = require('react-native-audio-recorder-player').default;
8
+ audioRecorderPlayer = new AudioRecorderPackage();
9
+ audioRecorderPlayer.setSubscriptionDuration(Platform.OS === 'android' ? 0.1 : 0.06);
10
+ } catch (e) {
11
+ console.log(e);
12
+ console.warn('react-native-audio-recorder-player is not installed.');
13
+ }
14
+
15
+ export enum AudioSourceAndroidType {
16
+ DEFAULT = 0,
17
+ MIC,
18
+ VOICE_UPLINK,
19
+ VOICE_DOWNLINK,
20
+ VOICE_CALL,
21
+ CAMCORDER,
22
+ VOICE_RECOGNITION,
23
+ VOICE_COMMUNICATION,
24
+ REMOTE_SUBMIX,
25
+ UNPROCESSED,
26
+ RADIO_TUNER = 1998,
27
+ HOTWORD,
28
+ }
29
+
30
+ export enum OutputFormatAndroidType {
31
+ DEFAULT = 0,
32
+ THREE_GPP,
33
+ MPEG_4,
34
+ AMR_NB,
35
+ AMR_WB,
36
+ AAC_ADIF,
37
+ AAC_ADTS,
38
+ OUTPUT_FORMAT_RTP_AVP,
39
+ MPEG_2_TS,
40
+ WEBM,
41
+ }
42
+
43
+ export enum AudioEncoderAndroidType {
44
+ DEFAULT = 0,
45
+ AMR_NB,
46
+ AMR_WB,
47
+ AAC,
48
+ HE_AAC,
49
+ AAC_ELD,
50
+ VORBIS,
51
+ }
52
+
53
+ export enum AVEncodingOption {
54
+ aac = 'aac',
55
+ alac = 'alac',
56
+ alaw = 'alaw',
57
+ amr = 'amr',
58
+ flac = 'flac',
59
+ ima4 = 'ima4',
60
+ lpcm = 'lpcm',
61
+ MAC3 = 'MAC3',
62
+ MAC6 = 'MAC6',
63
+ mp1 = 'mp1',
64
+ mp2 = 'mp2',
65
+ mp4 = 'mp4',
66
+ opus = 'opus',
67
+ ulaw = 'ulaw',
68
+ wav = 'wav',
69
+ }
70
+
71
+ export enum AVModeIOSOption {
72
+ gamechat = 'gamechat',
73
+ measurement = 'measurement',
74
+ movieplayback = 'movieplayback',
75
+ spokenaudio = 'spokenaudio',
76
+ videochat = 'videochat',
77
+ videorecording = 'videorecording',
78
+ voicechat = 'voicechat',
79
+ voiceprompt = 'voiceprompt',
80
+ }
81
+
82
+ export type AVModeIOSType =
83
+ | AVModeIOSOption.gamechat
84
+ | AVModeIOSOption.measurement
85
+ | AVModeIOSOption.movieplayback
86
+ | AVModeIOSOption.spokenaudio
87
+ | AVModeIOSOption.videochat
88
+ | AVModeIOSOption.videorecording
89
+ | AVModeIOSOption.voicechat
90
+ | AVModeIOSOption.voiceprompt;
91
+
92
+ export enum AVEncoderAudioQualityIOSType {
93
+ min = 0,
94
+ low = 32,
95
+ medium = 64,
96
+ high = 96,
97
+ max = 127,
98
+ }
99
+
100
+ export enum AVLinearPCMBitDepthKeyIOSType {
101
+ 'bit8' = 8,
102
+ 'bit16' = 16,
103
+ 'bit24' = 24,
104
+ 'bit32' = 32,
105
+ }
106
+
107
+ export type RecordingOptions = {
108
+ /**
109
+ * A boolean that determines whether audio level information will be part of the status object under the "metering" key.
110
+ */
111
+ isMeteringEnabled?: boolean;
112
+ };
113
+
114
+ const verifyAndroidPermissions = async () => {
115
+ const isRN71orAbove = Platform.constants.reactNativeVersion?.minor >= 71;
116
+ const isAndroid13orAbove = (Platform.Version as number) >= 33;
117
+ const shouldCheckForMediaPermissions = isRN71orAbove && isAndroid13orAbove;
118
+
119
+ const getCheckPermissionPromise = () => {
120
+ if (shouldCheckForMediaPermissions) {
121
+ return Promise.all([
122
+ PermissionsAndroid.check(PermissionsAndroid.PERMISSIONS.RECORD_AUDIO),
123
+ PermissionsAndroid.check(PermissionsAndroid.PERMISSIONS.READ_MEDIA_AUDIO),
124
+ ]).then(
125
+ ([hasRecordAudioPermission, hasReadMediaAudioPermission]) =>
126
+ hasRecordAudioPermission && hasReadMediaAudioPermission,
127
+ );
128
+ } else {
129
+ return Promise.all([
130
+ PermissionsAndroid.check(PermissionsAndroid.PERMISSIONS.RECORD_AUDIO),
131
+ PermissionsAndroid.check(PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE),
132
+ ]).then(
133
+ ([hasRecordAudioPermission, hasReadExternalStorage]) =>
134
+ hasRecordAudioPermission && hasReadExternalStorage,
135
+ );
136
+ }
137
+ };
138
+ const hasPermission = await getCheckPermissionPromise();
139
+ if (!hasPermission) {
140
+ const getRequestPermissionPromise = () => {
141
+ if (shouldCheckForMediaPermissions) {
142
+ return PermissionsAndroid.requestMultiple([
143
+ PermissionsAndroid.PERMISSIONS.RECORD_AUDIO,
144
+ PermissionsAndroid.PERMISSIONS.READ_MEDIA_AUDIO,
145
+ ]).then(
146
+ (statuses) =>
147
+ statuses[PermissionsAndroid.PERMISSIONS.RECORD_AUDIO] ===
148
+ PermissionsAndroid.RESULTS.GRANTED &&
149
+ statuses[PermissionsAndroid.PERMISSIONS.READ_MEDIA_AUDIO] ===
150
+ PermissionsAndroid.RESULTS.GRANTED,
151
+ );
152
+ } else {
153
+ return PermissionsAndroid.requestMultiple([
154
+ PermissionsAndroid.PERMISSIONS.RECORD_AUDIO,
155
+ PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE,
156
+ ]).then(
157
+ (statuses) =>
158
+ statuses[PermissionsAndroid.PERMISSIONS.RECORD_AUDIO] ===
159
+ PermissionsAndroid.RESULTS.GRANTED &&
160
+ statuses[PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE] ===
161
+ PermissionsAndroid.RESULTS.GRANTED,
162
+ );
163
+ }
164
+ };
165
+ const granted = await getRequestPermissionPromise();
166
+ return granted;
167
+ }
168
+ return true;
169
+ };
170
+
171
+ export const Audio = AudioRecorderPackage
172
+ ? {
173
+ pausePlayer: async () => {
174
+ console.log('Pause Player..');
175
+ await audioRecorderPlayer.pausePlayer();
176
+ },
177
+ resumePlayer: async () => {
178
+ console.log('Resume Player..');
179
+ await audioRecorderPlayer.resumePlayer();
180
+ },
181
+ startPlayer: async (uri, _, onPlaybackStatusUpdate) => {
182
+ try {
183
+ console.log('Starting Player..');
184
+ const playback = await audioRecorderPlayer.startPlayer(uri);
185
+ console.log({ playback });
186
+ audioRecorderPlayer.addPlayBackListener((status) => {
187
+ onPlaybackStatusUpdate(status);
188
+ });
189
+ } catch (error) {
190
+ console.log('Error starting player', error);
191
+ }
192
+ },
193
+ startRecording: async (options: RecordingOptions, onRecordingStatusUpdate) => {
194
+ console.log('Starting recording..');
195
+ if (Platform.OS === 'android') {
196
+ try {
197
+ await verifyAndroidPermissions();
198
+ } catch (err) {
199
+ console.warn('Audio Recording Permissions error', err);
200
+ return;
201
+ }
202
+ }
203
+ try {
204
+ const path = Platform.select({
205
+ android: `${RNFS.CachesDirectoryPath}/sound.aac`,
206
+ ios: 'sound.aac',
207
+ });
208
+ const audioSet = {
209
+ AudioEncoderAndroid: AudioEncoderAndroidType.AAC,
210
+ AudioSourceAndroid: AudioSourceAndroidType.MIC,
211
+ AVEncoderAudioQualityKeyIOS: AVEncoderAudioQualityIOSType.high,
212
+ AVFormatIDKeyIOS: AVEncodingOption.aac,
213
+ AVModeIOS: AVModeIOSOption.measurement,
214
+ AVNumberOfChannelsKeyIOS: 2,
215
+ OutputFormatAndroid: OutputFormatAndroidType.AAC_ADTS,
216
+ };
217
+ const recording = await audioRecorderPlayer.startRecorder(
218
+ path,
219
+ audioSet,
220
+ options?.isMeteringEnabled,
221
+ );
222
+
223
+ audioRecorderPlayer.addRecordBackListener((status) => {
224
+ onRecordingStatusUpdate(status);
225
+ });
226
+ return { accessGranted: true, recording };
227
+ } catch (error) {
228
+ console.error('Failed to start recording', error);
229
+ return { accessGranted: false, recording: null };
230
+ }
231
+ },
232
+ stopPlayer: async () => {
233
+ console.log('Stopping player..');
234
+ await audioRecorderPlayer.stopPlayer();
235
+ audioRecorderPlayer.removePlayBackListener();
236
+ },
237
+ stopRecording: async () => {
238
+ console.log('Stopping recording..');
239
+ await audioRecorderPlayer.stopRecorder();
240
+ audioRecorderPlayer.removeRecordBackListener();
241
+ },
242
+ }
243
+ : null;
@@ -1,3 +1,4 @@
1
+ export * from './Audio';
1
2
  export * from './shareImage';
2
3
  export * from './Video';
3
4
  export * from './triggerHaptic';