stream-chat-react-native-core 8.11.0-beta.1 → 8.11.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 (176) hide show
  1. package/lib/commonjs/components/Attachment/AudioAttachment.js +84 -209
  2. package/lib/commonjs/components/Attachment/AudioAttachment.js.map +1 -1
  3. package/lib/commonjs/components/Attachment/FileAttachmentGroup.js +8 -5
  4. package/lib/commonjs/components/Attachment/FileAttachmentGroup.js.map +1 -1
  5. package/lib/commonjs/components/Channel/Channel.js +20 -9
  6. package/lib/commonjs/components/Channel/Channel.js.map +1 -1
  7. package/lib/commonjs/components/Message/hooks/useMessageActionHandlers.js +4 -1
  8. package/lib/commonjs/components/Message/hooks/useMessageActionHandlers.js.map +1 -1
  9. package/lib/commonjs/components/MessageInput/MessageInput.js +2 -0
  10. package/lib/commonjs/components/MessageInput/MessageInput.js.map +1 -1
  11. package/lib/commonjs/components/MessageInput/components/AttachmentPreview/AudioAttachmentUploadPreview.js +9 -3
  12. package/lib/commonjs/components/MessageInput/components/AttachmentPreview/AudioAttachmentUploadPreview.js.map +1 -1
  13. package/lib/commonjs/components/MessageInput/components/AudioRecorder/AudioRecordingPreview.js +44 -8
  14. package/lib/commonjs/components/MessageInput/components/AudioRecorder/AudioRecordingPreview.js.map +1 -1
  15. package/lib/commonjs/components/MessageInput/hooks/useAudioController.js +5 -0
  16. package/lib/commonjs/components/MessageInput/hooks/useAudioController.js.map +1 -1
  17. package/lib/commonjs/components/MessageInput/hooks/useAudioPreviewManager.js.map +1 -1
  18. package/lib/commonjs/components/ProgressControl/ProgressControl.js +25 -33
  19. package/lib/commonjs/components/ProgressControl/ProgressControl.js.map +1 -1
  20. package/lib/commonjs/components/ProgressControl/WaveProgressBar.js +21 -29
  21. package/lib/commonjs/components/ProgressControl/WaveProgressBar.js.map +1 -1
  22. package/lib/commonjs/contexts/audioPlayerContext/AudioPlayerContext.js +56 -0
  23. package/lib/commonjs/contexts/audioPlayerContext/AudioPlayerContext.js.map +1 -0
  24. package/lib/commonjs/contexts/index.js +11 -0
  25. package/lib/commonjs/contexts/index.js.map +1 -1
  26. package/lib/commonjs/hooks/index.js +11 -0
  27. package/lib/commonjs/hooks/index.js.map +1 -1
  28. package/lib/commonjs/hooks/useAudioPlayer.js +18 -25
  29. package/lib/commonjs/hooks/useAudioPlayer.js.map +1 -1
  30. package/lib/commonjs/hooks/useAudioPlayerControl.js +43 -0
  31. package/lib/commonjs/hooks/useAudioPlayerControl.js.map +1 -0
  32. package/lib/commonjs/hooks/useInAppNotificationsState.js +1 -1
  33. package/lib/commonjs/i18n/es.json +1 -2
  34. package/lib/commonjs/i18n/he.json +5 -5
  35. package/lib/commonjs/i18n/ru.json +0 -5
  36. package/lib/commonjs/index.js +4 -4
  37. package/lib/commonjs/index.js.map +1 -1
  38. package/lib/commonjs/native.js.map +1 -1
  39. package/lib/commonjs/state-store/audio-player-pool.js +99 -0
  40. package/lib/commonjs/state-store/audio-player-pool.js.map +1 -0
  41. package/lib/commonjs/state-store/audio-player.js +373 -0
  42. package/lib/commonjs/state-store/audio-player.js.map +1 -0
  43. package/lib/commonjs/state-store/in-app-notifications-store.js.map +1 -0
  44. package/lib/commonjs/state-store/index.js +37 -0
  45. package/lib/commonjs/state-store/index.js.map +1 -0
  46. package/lib/commonjs/version.json +1 -1
  47. package/lib/module/components/Attachment/AudioAttachment.js +84 -209
  48. package/lib/module/components/Attachment/AudioAttachment.js.map +1 -1
  49. package/lib/module/components/Attachment/FileAttachmentGroup.js +8 -5
  50. package/lib/module/components/Attachment/FileAttachmentGroup.js.map +1 -1
  51. package/lib/module/components/Channel/Channel.js +20 -9
  52. package/lib/module/components/Channel/Channel.js.map +1 -1
  53. package/lib/module/components/Message/hooks/useMessageActionHandlers.js +4 -1
  54. package/lib/module/components/Message/hooks/useMessageActionHandlers.js.map +1 -1
  55. package/lib/module/components/MessageInput/MessageInput.js +2 -0
  56. package/lib/module/components/MessageInput/MessageInput.js.map +1 -1
  57. package/lib/module/components/MessageInput/components/AttachmentPreview/AudioAttachmentUploadPreview.js +9 -3
  58. package/lib/module/components/MessageInput/components/AttachmentPreview/AudioAttachmentUploadPreview.js.map +1 -1
  59. package/lib/module/components/MessageInput/components/AudioRecorder/AudioRecordingPreview.js +44 -8
  60. package/lib/module/components/MessageInput/components/AudioRecorder/AudioRecordingPreview.js.map +1 -1
  61. package/lib/module/components/MessageInput/hooks/useAudioController.js +5 -0
  62. package/lib/module/components/MessageInput/hooks/useAudioController.js.map +1 -1
  63. package/lib/module/components/MessageInput/hooks/useAudioPreviewManager.js.map +1 -1
  64. package/lib/module/components/ProgressControl/ProgressControl.js +25 -33
  65. package/lib/module/components/ProgressControl/ProgressControl.js.map +1 -1
  66. package/lib/module/components/ProgressControl/WaveProgressBar.js +21 -29
  67. package/lib/module/components/ProgressControl/WaveProgressBar.js.map +1 -1
  68. package/lib/module/contexts/audioPlayerContext/AudioPlayerContext.js +56 -0
  69. package/lib/module/contexts/audioPlayerContext/AudioPlayerContext.js.map +1 -0
  70. package/lib/module/contexts/index.js +11 -0
  71. package/lib/module/contexts/index.js.map +1 -1
  72. package/lib/module/hooks/index.js +11 -0
  73. package/lib/module/hooks/index.js.map +1 -1
  74. package/lib/module/hooks/useAudioPlayer.js +18 -25
  75. package/lib/module/hooks/useAudioPlayer.js.map +1 -1
  76. package/lib/module/hooks/useAudioPlayerControl.js +43 -0
  77. package/lib/module/hooks/useAudioPlayerControl.js.map +1 -0
  78. package/lib/module/hooks/useInAppNotificationsState.js +1 -1
  79. package/lib/module/i18n/es.json +1 -2
  80. package/lib/module/i18n/he.json +5 -5
  81. package/lib/module/i18n/ru.json +0 -5
  82. package/lib/module/index.js +4 -4
  83. package/lib/module/index.js.map +1 -1
  84. package/lib/module/native.js.map +1 -1
  85. package/lib/module/state-store/audio-player-pool.js +99 -0
  86. package/lib/module/state-store/audio-player-pool.js.map +1 -0
  87. package/lib/module/state-store/audio-player.js +373 -0
  88. package/lib/module/state-store/audio-player.js.map +1 -0
  89. package/lib/module/state-store/in-app-notifications-store.js.map +1 -0
  90. package/lib/module/state-store/index.js +37 -0
  91. package/lib/module/state-store/index.js.map +1 -0
  92. package/lib/module/version.json +1 -1
  93. package/lib/typescript/components/Attachment/AudioAttachment.d.ts +25 -5
  94. package/lib/typescript/components/Attachment/AudioAttachment.d.ts.map +1 -1
  95. package/lib/typescript/components/Attachment/FileAttachmentGroup.d.ts +2 -1
  96. package/lib/typescript/components/Attachment/FileAttachmentGroup.d.ts.map +1 -1
  97. package/lib/typescript/components/Channel/Channel.d.ts +5 -0
  98. package/lib/typescript/components/Channel/Channel.d.ts.map +1 -1
  99. package/lib/typescript/components/Message/hooks/useMessageActionHandlers.d.ts.map +1 -1
  100. package/lib/typescript/components/MessageInput/MessageInput.d.ts.map +1 -1
  101. package/lib/typescript/components/MessageInput/components/AttachmentPreview/AudioAttachmentUploadPreview.d.ts +17 -0
  102. package/lib/typescript/components/MessageInput/components/AttachmentPreview/AudioAttachmentUploadPreview.d.ts.map +1 -1
  103. package/lib/typescript/components/MessageInput/components/AudioRecorder/AudioRecordingPreview.d.ts +18 -4
  104. package/lib/typescript/components/MessageInput/components/AudioRecorder/AudioRecordingPreview.d.ts.map +1 -1
  105. package/lib/typescript/components/MessageInput/hooks/useAudioController.d.ts +2 -0
  106. package/lib/typescript/components/MessageInput/hooks/useAudioController.d.ts.map +1 -1
  107. package/lib/typescript/components/MessageInput/hooks/useAudioPreviewManager.d.ts +2 -0
  108. package/lib/typescript/components/MessageInput/hooks/useAudioPreviewManager.d.ts.map +1 -1
  109. package/lib/typescript/components/ProgressControl/ProgressControl.d.ts +2 -0
  110. package/lib/typescript/components/ProgressControl/ProgressControl.d.ts.map +1 -1
  111. package/lib/typescript/components/ProgressControl/WaveProgressBar.d.ts.map +1 -1
  112. package/lib/typescript/contexts/audioPlayerContext/AudioPlayerContext.d.ts +15 -0
  113. package/lib/typescript/contexts/audioPlayerContext/AudioPlayerContext.d.ts.map +1 -0
  114. package/lib/typescript/contexts/index.d.ts +1 -0
  115. package/lib/typescript/contexts/index.d.ts.map +1 -1
  116. package/lib/typescript/hooks/index.d.ts +1 -0
  117. package/lib/typescript/hooks/index.d.ts.map +1 -1
  118. package/lib/typescript/hooks/useAudioPlayer.d.ts +3 -1
  119. package/lib/typescript/hooks/useAudioPlayer.d.ts.map +1 -1
  120. package/lib/typescript/hooks/useAudioPlayerControl.d.ts +18 -0
  121. package/lib/typescript/hooks/useAudioPlayerControl.d.ts.map +1 -0
  122. package/lib/typescript/i18n/es.json +1 -2
  123. package/lib/typescript/i18n/he.json +5 -5
  124. package/lib/typescript/i18n/ru.json +0 -5
  125. package/lib/typescript/index.d.ts +1 -1
  126. package/lib/typescript/index.d.ts.map +1 -1
  127. package/lib/typescript/native.d.ts +1 -0
  128. package/lib/typescript/native.d.ts.map +1 -1
  129. package/lib/typescript/state-store/audio-player-pool.d.ts +24 -0
  130. package/lib/typescript/state-store/audio-player-pool.d.ts.map +1 -0
  131. package/lib/typescript/state-store/audio-player.d.ts +62 -0
  132. package/lib/typescript/state-store/audio-player.d.ts.map +1 -0
  133. package/lib/typescript/state-store/in-app-notifications-store.d.ts.map +1 -0
  134. package/lib/typescript/state-store/index.d.ts +4 -0
  135. package/lib/typescript/state-store/index.d.ts.map +1 -0
  136. package/package.json +6 -5
  137. package/src/components/Attachment/AudioAttachment.tsx +118 -198
  138. package/src/components/Attachment/FileAttachmentGroup.tsx +35 -16
  139. package/src/components/Channel/Channel.tsx +21 -4
  140. package/src/components/Message/hooks/useMessageActionHandlers.ts +3 -1
  141. package/src/components/MessageInput/MessageInput.tsx +6 -0
  142. package/src/components/MessageInput/components/AttachmentPreview/AudioAttachmentUploadPreview.tsx +29 -2
  143. package/src/components/MessageInput/components/AudioRecorder/AudioRecordingPreview.tsx +73 -9
  144. package/src/components/MessageInput/hooks/useAudioController.tsx +62 -1
  145. package/src/components/MessageInput/hooks/useAudioPreviewManager.tsx +28 -5
  146. package/src/components/ProgressControl/ProgressControl.tsx +45 -47
  147. package/src/components/ProgressControl/WaveProgressBar.tsx +37 -36
  148. package/src/contexts/audioPlayerContext/AudioPlayerContext.tsx +55 -0
  149. package/src/contexts/index.ts +1 -0
  150. package/src/hooks/index.ts +1 -0
  151. package/src/hooks/useAudioPlayer.ts +7 -8
  152. package/src/hooks/useAudioPlayerControl.ts +59 -0
  153. package/src/hooks/useInAppNotificationsState.ts +2 -2
  154. package/src/i18n/es.json +1 -2
  155. package/src/i18n/he.json +5 -5
  156. package/src/i18n/ru.json +0 -5
  157. package/src/index.ts +1 -1
  158. package/src/native.ts +1 -0
  159. package/src/state-store/audio-player-pool.ts +94 -0
  160. package/src/state-store/audio-player.ts +372 -0
  161. package/src/state-store/index.ts +3 -0
  162. package/src/version.json +1 -1
  163. package/lib/commonjs/store/in-app-notifications-store.js.map +0 -1
  164. package/lib/commonjs/store/index.js +0 -15
  165. package/lib/commonjs/store/index.js.map +0 -1
  166. package/lib/module/store/in-app-notifications-store.js.map +0 -1
  167. package/lib/module/store/index.js +0 -15
  168. package/lib/module/store/index.js.map +0 -1
  169. package/lib/typescript/store/in-app-notifications-store.d.ts.map +0 -1
  170. package/lib/typescript/store/index.d.ts +0 -2
  171. package/lib/typescript/store/index.d.ts.map +0 -1
  172. package/src/store/index.ts +0 -1
  173. /package/lib/commonjs/{store → state-store}/in-app-notifications-store.js +0 -0
  174. /package/lib/module/{store → state-store}/in-app-notifications-store.js +0 -0
  175. /package/lib/typescript/{store → state-store}/in-app-notifications-store.d.ts +0 -0
  176. /package/src/{store → state-store}/in-app-notifications-store.ts +0 -0
@@ -0,0 +1,62 @@
1
+ import { StateStore } from 'stream-chat';
2
+ import { AudioPlayerPool } from './audio-player-pool';
3
+ import { SoundReturnType } from '../native';
4
+ export type AudioDescriptor = {
5
+ id: string;
6
+ uri: string;
7
+ duration: number;
8
+ mimeType: string;
9
+ type: 'voiceRecording' | 'audio';
10
+ };
11
+ export type AudioPlayerState = {
12
+ isPlaying: boolean;
13
+ duration: number;
14
+ position: number;
15
+ progress: number;
16
+ currentPlaybackRate: number;
17
+ playbackRates: number[];
18
+ };
19
+ export type AudioPlayerOptions = AudioDescriptor & {
20
+ playbackRates?: number[];
21
+ previewVoiceRecording?: boolean;
22
+ };
23
+ export declare class AudioPlayer {
24
+ state: StateStore<AudioPlayerState>;
25
+ playerRef: SoundReturnType | null;
26
+ private _id;
27
+ private type;
28
+ private isExpoCLI;
29
+ private _pool;
30
+ /**
31
+ * This is a temporary flag to manage audio player for voice recording in preview as the one in message list uses react-native-video.
32
+ * We can get rid of this when we migrate to the react-native-nitro-sound everywhere.
33
+ */
34
+ private previewVoiceRecording?;
35
+ constructor(options: AudioPlayerOptions);
36
+ initPlayer: ({ uri, playerRef }: {
37
+ uri?: string;
38
+ playerRef?: SoundReturnType;
39
+ }) => Promise<void>;
40
+ private onVoiceRecordingPreviewPlaybackStatusUpdate;
41
+ private onPlaybackStatusUpdate;
42
+ get isPlaying(): boolean;
43
+ get duration(): number;
44
+ get position(): number;
45
+ get progress(): number;
46
+ get playbackRates(): number[];
47
+ get currentPlaybackRate(): number;
48
+ get id(): string;
49
+ set pool(pool: AudioPlayerPool);
50
+ set duration(duration: number);
51
+ set position(position: number);
52
+ set progress(progress: number);
53
+ set isPlaying(isPlaying: boolean);
54
+ changePlaybackRate(): Promise<void>;
55
+ play(): void;
56
+ pause(): void;
57
+ toggle(): void;
58
+ seek(positionInSeconds: number): Promise<void>;
59
+ stop(): Promise<void>;
60
+ onRemove(): void;
61
+ }
62
+ //# sourceMappingURL=audio-player.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audio-player.d.ts","sourceRoot":"","sources":["../../../src/state-store/audio-player.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAEtD,OAAO,EAAyD,eAAe,EAAE,MAAM,WAAW,CAAC;AAEnG,MAAM,MAAM,eAAe,GAAG;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,aAAa,EAAE,MAAM,EAAE,CAAC;CACzB,CAAC;AAmBF,MAAM,MAAM,kBAAkB,GAAG,eAAe,GAAG;IACjD,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC,CAAC;AAEF,qBAAa,WAAW;IACtB,KAAK,EAAE,UAAU,CAAC,gBAAgB,CAAC,CAAC;IACpC,SAAS,EAAE,eAAe,GAAG,IAAI,CAAQ;IACzC,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,IAAI,CAA6B;IACzC,OAAO,CAAC,SAAS,CAAU;IAC3B,OAAO,CAAC,KAAK,CAAgC;IAE7C;;;OAGG;IACH,OAAO,CAAC,qBAAqB,CAAC,CAAU;gBAE5B,OAAO,EAAE,kBAAkB;IAiBvC,UAAU,GAAU,oBAAoB;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,eAAe,CAAA;KAAE,mBA4BnF;IAEF,OAAO,CAAC,2CAA2C,CAOjD;IAGF,OAAO,CAAC,sBAAsB,CA6B5B;IAGF,IAAI,SAAS,IAqDY,OAAO,CAnD/B;IAED,IAAI,QAAQ,IA6BW,MAAM,CA3B5B;IAED,IAAI,QAAQ,IA+BW,MAAM,CA7B5B;IAED,IAAI,QAAQ,IAkCW,MAAM,CAhC5B;IAED,IAAI,aAAa,aAEhB;IAED,IAAI,mBAAmB,WAEtB;IAED,IAAI,EAAE,WAEL;IAGD,IAAI,IAAI,CAAC,IAAI,EAAE,eAAe,EAE7B;IAED,IAAI,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAI5B;IAED,IAAI,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAK5B;IAED,IAAI,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAK5B;IAED,IAAI,SAAS,CAAC,SAAS,EAAE,OAAO,EAI/B;IAGK,kBAAkB;IAqBxB,IAAI;IAqCJ,KAAK;IAoCL,MAAM;IAQA,IAAI,CAAC,iBAAiB,EAAE,MAAM;IA8B9B,IAAI;IAMV,QAAQ;CAyBT"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"in-app-notifications-store.d.ts","sourceRoot":"","sources":["../../../src/state-store/in-app-notifications-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEvD,MAAM,MAAM,uBAAuB,GAAG;IACpC,aAAa,EAAE,YAAY,EAAE,CAAC;CAC/B,CAAC;AAMF,eAAO,MAAM,uBAAuB,qCAAyD,CAAC;AAE9F,eAAO,MAAM,qBAAqB,GAAI,cAAc,YAAY,SAgB/D,CAAC;AAEF,eAAO,MAAM,sBAAsB,GAAI,IAAI,MAAM,SAShD,CAAC"}
@@ -0,0 +1,4 @@
1
+ export * from './audio-player';
2
+ export * from './in-app-notifications-store';
3
+ export * from './audio-player-pool';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/state-store/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,8BAA8B,CAAC;AAC7C,cAAc,qBAAqB,CAAC"}
package/package.json CHANGED
@@ -1,14 +1,15 @@
1
1
  {
2
2
  "name": "stream-chat-react-native-core",
3
3
  "description": "The official React Native and Expo components for Stream Chat, a service for building chat applications",
4
- "version": "8.11.0-beta.1",
4
+ "version": "8.11.0",
5
5
  "author": {
6
6
  "company": "Stream.io Inc",
7
7
  "name": "Stream.io Inc"
8
8
  },
9
9
  "repository": {
10
10
  "type": "git",
11
- "url": "https://github.com/GetStream/stream-chat-react-native.git"
11
+ "url": "https://github.com/GetStream/stream-chat-react-native.git",
12
+ "directory": "package"
12
13
  },
13
14
  "license": "SEE LICENSE IN LICENSE",
14
15
  "main": "lib/commonjs/index.js",
@@ -24,7 +25,7 @@
24
25
  "scripts": {
25
26
  "install-all": "(yarn install --force && (cd native-package && yarn install --force) && (cd expo-package && yarn install --force))",
26
27
  "build": "rimraf lib && yarn run --silent build-translations && bob build && yarn run --silent copy-translations",
27
- "build-translations": "i18next",
28
+ "build-translations": "i18next-cli sync",
28
29
  "copy-translations": "echo '\u001b[34mℹ\u001b[0m Copying translation files to \u001b[34mlib/typescript/i18n\u001b[0m' && cp -R -f ./src/i18n ./lib/typescript/i18n && echo '\u001b[32m✓\u001b[0m Done Copying Translations'",
29
30
  "eslint": "eslint 'src/**/*.{js,md,ts,jsx,tsx}' --max-warnings 0",
30
31
  "lint": "prettier --ignore-path ../.prettierignore --list-different 'src/**/*.{js,ts,tsx,md,json}' eslint.config.mjs ../.prettierrc babel.config.js && eslint 'src/**/*.{js,ts,tsx,md}' --max-warnings 0 && yarn run validate-translations",
@@ -112,11 +113,11 @@
112
113
  "@babel/core": "^7.27.4",
113
114
  "@babel/runtime": "^7.27.6",
114
115
  "@op-engineering/op-sqlite": "^14.0.3",
115
- "@shopify/flash-list": "^2.1.0",
116
116
  "@react-native-community/eslint-config": "3.2.0",
117
117
  "@react-native-community/eslint-plugin": "1.3.0",
118
118
  "@react-native-community/netinfo": "^11.4.1",
119
119
  "@react-native/babel-preset": "0.79.3",
120
+ "@shopify/flash-list": "^2.1.0",
120
121
  "@testing-library/jest-native": "^5.4.3",
121
122
  "@testing-library/react-native": "13.2.0",
122
123
  "@types/better-sqlite3": "^7.6.13",
@@ -145,7 +146,7 @@
145
146
  "eslint-plugin-react": "^7.37.5",
146
147
  "eslint-plugin-react-hooks": "^5.2.0",
147
148
  "eslint-plugin-react-native": "^5.0.0",
148
- "i18next-parser": "^9.3.0",
149
+ "i18next-cli": "^1.31.0",
149
150
  "jest": "^30.0.0",
150
151
  "moment-timezone": "^0.6.0",
151
152
  "prettier": "^3.5.3",
@@ -1,254 +1,179 @@
1
- import React, { RefObject, useEffect, useMemo, useState } from 'react';
1
+ import React, { RefObject, useEffect, useMemo } from 'react';
2
2
  import { I18nManager, Pressable, StyleSheet, Text, View } from 'react-native';
3
3
 
4
4
  import dayjs from 'dayjs';
5
5
  import duration from 'dayjs/plugin/duration';
6
6
 
7
- import { AudioAttachment as StreamAudioAttachment } from 'stream-chat';
7
+ import {
8
+ isVoiceRecordingAttachment,
9
+ LocalMessage,
10
+ AudioAttachment as StreamAudioAttachment,
11
+ VoiceRecordingAttachment as StreamVoiceRecordingAttachment,
12
+ } from 'stream-chat';
8
13
 
9
14
  import { useTheme } from '../../contexts';
10
- import { useAudioPlayer } from '../../hooks/useAudioPlayer';
15
+ import { useStateStore } from '../../hooks';
16
+ import { useAudioPlayerControl } from '../../hooks/useAudioPlayerControl';
11
17
  import { Audio, Pause, Play } from '../../icons';
12
18
  import {
13
19
  NativeHandlers,
14
- PlaybackStatus,
15
20
  SoundReturnType,
16
21
  VideoPayloadData,
17
22
  VideoProgressData,
18
23
  VideoSeekResponse,
19
24
  } from '../../native';
20
- import { AudioConfig, FileTypes } from '../../types/types';
25
+ import { AudioPlayerState } from '../../state-store/audio-player';
26
+ import { AudioConfig } from '../../types/types';
21
27
  import { getTrimmedAttachmentTitle } from '../../utils/getTrimmedAttachmentTitle';
22
28
  import { ProgressControl } from '../ProgressControl/ProgressControl';
23
29
  import { WaveProgressBar } from '../ProgressControl/WaveProgressBar';
24
30
 
31
+ const ONE_HOUR_IN_MILLISECONDS = 3600 * 1000;
32
+ const ONE_SECOND_IN_MILLISECONDS = 1000;
33
+
25
34
  dayjs.extend(duration);
26
35
 
27
36
  export type AudioAttachmentType = AudioConfig &
28
- Pick<StreamAudioAttachment, 'waveform_data' | 'asset_url' | 'title'> & {
37
+ Pick<
38
+ StreamAudioAttachment | StreamVoiceRecordingAttachment,
39
+ 'waveform_data' | 'asset_url' | 'title' | 'mime_type'
40
+ > & {
29
41
  id: string;
30
42
  type: 'audio' | 'voiceRecording';
31
43
  };
32
44
 
33
45
  export type AudioAttachmentProps = {
34
46
  item: AudioAttachmentType;
35
- onLoad: (index: string, duration: number) => void;
36
- onPlayPause: (index: string, pausedStatus?: boolean) => void;
37
- onProgress: (index: string, progress: number) => void;
47
+ message?: LocalMessage;
38
48
  titleMaxLength?: number;
39
49
  hideProgressBar?: boolean;
50
+ /**
51
+ * If true, the speed settings button will be shown.
52
+ */
40
53
  showSpeedSettings?: boolean;
41
54
  testID?: string;
55
+ /**
56
+ * If true, the audio attachment is in preview mode in the message input.
57
+ */
58
+ isPreview?: boolean;
59
+ /**
60
+ * Callback to be called when the audio is loaded
61
+ * @deprecated This is deprecated and will be removed in the future.
62
+ */
63
+ onLoad?: (index: string, duration: number) => void;
64
+ /**
65
+ * Callback to be called when the audio is played or paused
66
+ * @deprecated This is deprecated and will be removed in the future.
67
+ */
68
+ onPlayPause?: (index: string, pausedStatus?: boolean) => void;
69
+ /**
70
+ * Callback to be called when the audio progresses
71
+ * @deprecated This is deprecated and will be removed in the future.
72
+ */
73
+ onProgress?: (index: string, progress: number) => void;
42
74
  };
43
75
 
76
+ const audioPlayerSelector = (state: AudioPlayerState) => ({
77
+ currentPlaybackRate: state.currentPlaybackRate,
78
+ duration: state.duration,
79
+ isPlaying: state.isPlaying,
80
+ position: state.position,
81
+ progress: state.progress,
82
+ });
83
+
44
84
  /**
45
85
  * AudioAttachment
46
86
  * UI Component to preview the audio files
47
87
  */
48
88
  export const AudioAttachment = (props: AudioAttachmentProps) => {
49
- const [currentSpeed, setCurrentSpeed] = useState<number>(1.0);
50
- const [audioFinished, setAudioFinished] = useState(false);
51
89
  const soundRef = React.useRef<SoundReturnType | null>(null);
90
+
52
91
  const {
53
92
  hideProgressBar = false,
54
93
  item,
55
- onLoad,
56
- onPlayPause,
57
- onProgress,
94
+ message,
58
95
  showSpeedSettings = false,
59
96
  testID,
60
97
  titleMaxLength,
98
+ isPreview = false,
61
99
  } = props;
62
- const { changeAudioSpeed, pauseAudio, playAudio, seekAudio } = useAudioPlayer({ soundRef });
63
- const isExpoCLI = NativeHandlers.SDK === 'stream-chat-expo';
64
- const isVoiceRecording = item.type === FileTypes.VoiceRecording;
100
+ const isVoiceRecording = isVoiceRecordingAttachment(item);
101
+
102
+ const audioPlayer = useAudioPlayerControl({
103
+ duration: item.duration ?? 0,
104
+ mimeType: item.mime_type ?? '',
105
+ requester: isPreview
106
+ ? 'preview'
107
+ : message?.id && `${message?.parent_id ?? message?.id}${message?.id}`,
108
+ type: isVoiceRecording ? 'voiceRecording' : 'audio',
109
+ uri: item.asset_url ?? '',
110
+ });
111
+ const { duration, isPlaying, position, progress, currentPlaybackRate } = useStateStore(
112
+ audioPlayer.state,
113
+ audioPlayerSelector,
114
+ );
115
+
116
+ // Initialize the player for native cli apps
117
+ useEffect(() => {
118
+ if (soundRef.current) {
119
+ audioPlayer.initPlayer({ playerRef: soundRef.current });
120
+ }
121
+ }, [audioPlayer]);
122
+
123
+ // When a audio attachment in preview is removed, we need to remove the player from the pool
124
+ useEffect(
125
+ () => () => {
126
+ if (isPreview) {
127
+ audioPlayer.onRemove();
128
+ }
129
+ },
130
+ [audioPlayer, isPreview],
131
+ );
65
132
 
66
133
  /** This is for Native CLI Apps */
67
134
  const handleLoad = (payload: VideoPayloadData) => {
68
- // The duration given by the rn-video is not same as the one of the voice recording, so we take the actual duration for voice recording.
69
- if (isVoiceRecording && item.duration) {
70
- onLoad(item.id, item.duration);
71
- } else {
72
- onLoad(item.id, item.duration || payload.duration);
135
+ // If the attachment is a voice recording, we rely on the duration from the attachment as the one from the react-native-video is incorrect.
136
+ if (isVoiceRecording) {
137
+ return;
73
138
  }
139
+ audioPlayer.duration = payload.duration * ONE_SECOND_IN_MILLISECONDS;
74
140
  };
75
141
 
76
142
  /** This is for Native CLI Apps */
77
143
  const handleProgress = (data: VideoProgressData) => {
78
- const { currentTime, seekableDuration } = data;
79
- // The duration given by the rn-video is not same as the one of the voice recording, so we take the actual duration for voice recording.
80
- if (isVoiceRecording && item.duration) {
81
- if (currentTime < item.duration && !audioFinished) {
82
- onProgress(item.id, currentTime / item.duration);
83
- } else {
84
- setAudioFinished(true);
85
- }
86
- } else {
87
- if (currentTime < seekableDuration && !audioFinished) {
88
- onProgress(item.id, currentTime / seekableDuration);
89
- } else {
90
- setAudioFinished(true);
91
- }
92
- }
144
+ const { currentTime } = data;
145
+ audioPlayer.position = currentTime * ONE_SECOND_IN_MILLISECONDS;
93
146
  };
94
147
 
95
148
  /** This is for Native CLI Apps */
96
149
  const onSeek = (seekResponse: VideoSeekResponse) => {
97
- setAudioFinished(false);
98
- onProgress(item.id, seekResponse.currentTime / (item.duration as number));
150
+ audioPlayer.position = seekResponse.currentTime * ONE_SECOND_IN_MILLISECONDS;
99
151
  };
100
152
 
101
- const handlePlayPause = async () => {
102
- if (item.paused) {
103
- if (isExpoCLI) {
104
- await playAudio();
105
- }
106
- onPlayPause(item.id, false);
107
- } else {
108
- if (isExpoCLI) {
109
- await pauseAudio();
110
- }
111
- onPlayPause(item.id, true);
112
- }
153
+ const handlePlayPause = () => {
154
+ audioPlayer.toggle();
113
155
  };
114
156
 
115
157
  const handleEnd = async () => {
116
- setAudioFinished(false);
117
- await pauseAudio();
118
- onPlayPause(item.id, true);
119
- await seekAudio(0);
120
- };
121
-
122
- const dragStart = async () => {
123
- if (isExpoCLI) {
124
- await pauseAudio();
125
- }
126
- onPlayPause(item.id, true);
158
+ await audioPlayer.stop();
127
159
  };
128
160
 
129
- const dragProgress = (progress: number) => {
130
- onProgress(item.id, progress);
161
+ const dragStart = () => {
162
+ audioPlayer.pause();
131
163
  };
132
164
 
133
- const dragEnd = async (progress: number) => {
134
- await seekAudio(progress * (item.duration as number));
135
- if (isExpoCLI) {
136
- await playAudio();
137
- }
138
- onPlayPause(item.id, false);
165
+ const dragProgress = (currentProgress: number) => {
166
+ audioPlayer.progress = currentProgress;
139
167
  };
140
168
 
141
- /** For Expo CLI */
142
- const onPlaybackStatusUpdate = (playbackStatus: PlaybackStatus) => {
143
- if (!playbackStatus.isLoaded) {
144
- // Update your UI for the unloaded state
145
- if (playbackStatus.error) {
146
- console.log(`Encountered a fatal error during playback: ${playbackStatus.error}`);
147
- }
148
- } else {
149
- const { durationMillis, positionMillis } = playbackStatus;
150
- // This is done for Expo CLI where we don't get file duration from file picker
151
- if (item.duration === 0) {
152
- onLoad(item.id, durationMillis / 1000);
153
- } else {
154
- // The duration given by the expo-av is not same as the one of the voice recording, so we take the actual duration for voice recording.
155
- if (isVoiceRecording && item.duration) {
156
- onLoad(item.id, item.duration);
157
- } else {
158
- onLoad(item.id, durationMillis / 1000);
159
- }
160
- }
161
- // Update your UI for the loaded state
162
- if (playbackStatus.isPlaying) {
163
- if (isVoiceRecording && item.duration) {
164
- if (positionMillis <= item.duration * 1000) {
165
- onProgress(item.id, positionMillis / (item.duration * 1000));
166
- }
167
- } else {
168
- if (positionMillis <= durationMillis) {
169
- onProgress(item.id, positionMillis / durationMillis);
170
- }
171
- }
172
- } else {
173
- // Update your UI for the paused state
174
- }
175
-
176
- if (playbackStatus.isBuffering) {
177
- // Update your UI for the buffering state
178
- }
179
-
180
- if (playbackStatus.didJustFinish && !playbackStatus.isLooping) {
181
- onProgress(item.id, 1);
182
- // The player has just finished playing and will stop. Maybe you want to play something else?
183
- // status: opposite of pause,says i am playing
184
- handleEnd();
185
- }
186
- }
169
+ const dragEnd = async (currentProgress: number) => {
170
+ const positionInSeconds = (currentProgress * duration) / ONE_SECOND_IN_MILLISECONDS;
171
+ await audioPlayer.seek(positionInSeconds);
172
+ audioPlayer.play();
187
173
  };
188
174
 
189
- // This is for Expo CLI, sound initialization is done here.
190
- useEffect(() => {
191
- if (isExpoCLI) {
192
- const initiateSound = async () => {
193
- if (item && item.asset_url && NativeHandlers.Sound?.initializeSound) {
194
- soundRef.current = await NativeHandlers.Sound.initializeSound(
195
- { uri: item.asset_url },
196
- {
197
- pitchCorrectionQuality: 'high',
198
- progressUpdateIntervalMillis: 100,
199
- shouldCorrectPitch: true,
200
- },
201
- onPlaybackStatusUpdate,
202
- );
203
- }
204
- };
205
- initiateSound();
206
- }
207
-
208
- return () => {
209
- if (soundRef.current?.stopAsync && soundRef.current.unloadAsync) {
210
- soundRef.current.stopAsync();
211
- soundRef.current.unloadAsync();
212
- }
213
- };
214
- // eslint-disable-next-line react-hooks/exhaustive-deps
215
- }, []);
216
-
217
- // This is needed for expo applications where the rerender doesn't occur on time thefore you need to update the state of the sound.
218
- useEffect(() => {
219
- const initalPlayPause = async () => {
220
- if (!isExpoCLI) {
221
- return;
222
- }
223
- try {
224
- if (item.paused) {
225
- await pauseAudio();
226
- } else {
227
- await playAudio();
228
- }
229
- } catch (e) {
230
- console.log('An error has occurred while trying to interact with the audio. ', e);
231
- }
232
- };
233
- // For expo CLI
234
- if (!NativeHandlers.Sound?.Player) {
235
- initalPlayPause();
236
- }
237
- }, [item.paused, isExpoCLI, pauseAudio, playAudio]);
238
-
239
175
  const onSpeedChangeHandler = async () => {
240
- if (currentSpeed === 2.0) {
241
- setCurrentSpeed(1.0);
242
- await changeAudioSpeed(1.0);
243
- } else {
244
- if (currentSpeed === 1.0) {
245
- setCurrentSpeed(1.5);
246
- await changeAudioSpeed(1.5);
247
- } else if (currentSpeed === 1.5) {
248
- setCurrentSpeed(2.0);
249
- await changeAudioSpeed(2.0);
250
- }
251
- }
176
+ await audioPlayer.changePlaybackRate();
252
177
  };
253
178
 
254
179
  const {
@@ -270,19 +195,14 @@ export const AudioAttachment = (props: AudioAttachmentProps) => {
270
195
  },
271
196
  } = useTheme();
272
197
 
273
- const progressValueInSeconds = useMemo(
274
- () => (item.duration as number) * (item.progress as number),
275
- [item.duration, item.progress],
276
- );
277
-
278
198
  const progressDuration = useMemo(
279
199
  () =>
280
- progressValueInSeconds
281
- ? progressValueInSeconds / 3600 >= 1
282
- ? dayjs.duration(progressValueInSeconds, 'second').format('HH:mm:ss')
283
- : dayjs.duration(progressValueInSeconds, 'second').format('mm:ss')
284
- : dayjs.duration(item.duration ?? 0, 'second').format('mm:ss'),
285
- [progressValueInSeconds, item.duration],
200
+ position
201
+ ? position / ONE_HOUR_IN_MILLISECONDS >= 1
202
+ ? dayjs.duration(position, 'milliseconds').format('HH:mm:ss')
203
+ : dayjs.duration(position, 'milliseconds').format('mm:ss')
204
+ : dayjs.duration(duration, 'milliseconds').format('mm:ss'),
205
+ [duration, position],
286
206
  );
287
207
 
288
208
  return (
@@ -308,7 +228,7 @@ export const AudioAttachment = (props: AudioAttachmentProps) => {
308
228
  playPauseButton,
309
229
  ]}
310
230
  >
311
- {item.paused ? (
231
+ {!isPlaying ? (
312
232
  <Play fill={static_black} height={32} width={32} />
313
233
  ) : (
314
234
  <Pause fill={static_black} height={32} width={32} />
@@ -328,7 +248,7 @@ export const AudioAttachment = (props: AudioAttachmentProps) => {
328
248
  filenameText,
329
249
  ]}
330
250
  >
331
- {item.type === FileTypes.VoiceRecording
251
+ {isVoiceRecordingAttachment(item)
332
252
  ? 'Recording'
333
253
  : getTrimmedAttachmentTitle(item.title, titleMaxLength)}
334
254
  </Text>
@@ -344,17 +264,17 @@ export const AudioAttachment = (props: AudioAttachmentProps) => {
344
264
  onEndDrag={dragEnd}
345
265
  onProgressDrag={dragProgress}
346
266
  onStartDrag={dragStart}
347
- progress={item.progress as number}
267
+ progress={progress}
348
268
  waveformData={item.waveform_data}
349
269
  />
350
270
  ) : (
351
271
  <ProgressControl
352
- duration={item.duration as number}
272
+ duration={duration}
353
273
  filledColor={accent_blue}
354
274
  onEndDrag={dragEnd}
355
275
  onProgressDrag={dragProgress}
356
276
  onStartDrag={dragStart}
357
- progress={item.progress as number}
277
+ progress={progress}
358
278
  testID='progress-control'
359
279
  />
360
280
  )}
@@ -367,8 +287,8 @@ export const AudioAttachment = (props: AudioAttachmentProps) => {
367
287
  onLoad={handleLoad}
368
288
  onProgress={handleProgress}
369
289
  onSeek={onSeek}
370
- paused={item.paused}
371
- rate={currentSpeed}
290
+ paused={!isPlaying}
291
+ rate={currentPlaybackRate}
372
292
  soundRef={soundRef as RefObject<SoundReturnType>}
373
293
  testID='sound-player'
374
294
  uri={item.asset_url}
@@ -377,7 +297,7 @@ export const AudioAttachment = (props: AudioAttachmentProps) => {
377
297
  </View>
378
298
  {showSpeedSettings ? (
379
299
  <View style={[styles.rightContainer, rightContainer]}>
380
- {item.paused ? (
300
+ {!isPlaying ? (
381
301
  <Audio fill={'#ffffff'} />
382
302
  ) : (
383
303
  <Pressable
@@ -390,7 +310,7 @@ export const AudioAttachment = (props: AudioAttachmentProps) => {
390
310
  >
391
311
  <Text
392
312
  style={[styles.speedChangeButtonText, speedChangeButtonText]}
393
- >{`x${currentSpeed.toFixed(1)}`}</Text>
313
+ >{`x${currentPlaybackRate.toFixed(1)}`}</Text>
394
314
  </Pressable>
395
315
  )}
396
316
  </View>