stream-chat-react-native-core 8.10.1 → 8.11.0-beta.3

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 (189) 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/AttachmentPicker/components/AttachmentPickerBottomSheetHandle.js +7 -3
  6. package/lib/commonjs/components/AttachmentPicker/components/AttachmentPickerBottomSheetHandle.js.map +1 -1
  7. package/lib/commonjs/components/Channel/Channel.js +20 -9
  8. package/lib/commonjs/components/Channel/Channel.js.map +1 -1
  9. package/lib/commonjs/components/Message/hooks/useMessageActionHandlers.js +4 -1
  10. package/lib/commonjs/components/Message/hooks/useMessageActionHandlers.js.map +1 -1
  11. package/lib/commonjs/components/MessageInput/MessageInput.js +2 -0
  12. package/lib/commonjs/components/MessageInput/MessageInput.js.map +1 -1
  13. package/lib/commonjs/components/MessageInput/components/AttachmentPreview/AudioAttachmentUploadPreview.js +9 -3
  14. package/lib/commonjs/components/MessageInput/components/AttachmentPreview/AudioAttachmentUploadPreview.js.map +1 -1
  15. package/lib/commonjs/components/MessageInput/components/AudioRecorder/AudioRecordingPreview.js +44 -8
  16. package/lib/commonjs/components/MessageInput/components/AudioRecorder/AudioRecordingPreview.js.map +1 -1
  17. package/lib/commonjs/components/MessageInput/hooks/useAudioController.js +5 -0
  18. package/lib/commonjs/components/MessageInput/hooks/useAudioController.js.map +1 -1
  19. package/lib/commonjs/components/MessageInput/hooks/useAudioPreviewManager.js.map +1 -1
  20. package/lib/commonjs/components/ProgressControl/ProgressControl.js +25 -33
  21. package/lib/commonjs/components/ProgressControl/ProgressControl.js.map +1 -1
  22. package/lib/commonjs/components/ProgressControl/WaveProgressBar.js +21 -29
  23. package/lib/commonjs/components/ProgressControl/WaveProgressBar.js.map +1 -1
  24. package/lib/commonjs/contexts/audioPlayerContext/AudioPlayerContext.js +56 -0
  25. package/lib/commonjs/contexts/audioPlayerContext/AudioPlayerContext.js.map +1 -0
  26. package/lib/commonjs/contexts/index.js +11 -0
  27. package/lib/commonjs/contexts/index.js.map +1 -1
  28. package/lib/commonjs/contexts/themeContext/utils/theme.js +4 -0
  29. package/lib/commonjs/contexts/themeContext/utils/theme.js.map +1 -1
  30. package/lib/commonjs/hooks/index.js +11 -0
  31. package/lib/commonjs/hooks/index.js.map +1 -1
  32. package/lib/commonjs/hooks/useAudioPlayer.js +18 -25
  33. package/lib/commonjs/hooks/useAudioPlayer.js.map +1 -1
  34. package/lib/commonjs/hooks/useAudioPlayerControl.js +43 -0
  35. package/lib/commonjs/hooks/useAudioPlayerControl.js.map +1 -0
  36. package/lib/commonjs/hooks/useInAppNotificationsState.js +1 -1
  37. package/lib/commonjs/i18n/es.json +1 -2
  38. package/lib/commonjs/i18n/he.json +5 -5
  39. package/lib/commonjs/i18n/ru.json +0 -5
  40. package/lib/commonjs/index.js +4 -4
  41. package/lib/commonjs/index.js.map +1 -1
  42. package/lib/commonjs/native.js.map +1 -1
  43. package/lib/commonjs/state-store/audio-player-pool.js +99 -0
  44. package/lib/commonjs/state-store/audio-player-pool.js.map +1 -0
  45. package/lib/commonjs/state-store/audio-player.js +373 -0
  46. package/lib/commonjs/state-store/audio-player.js.map +1 -0
  47. package/lib/commonjs/state-store/in-app-notifications-store.js.map +1 -0
  48. package/lib/commonjs/state-store/index.js +37 -0
  49. package/lib/commonjs/state-store/index.js.map +1 -0
  50. package/lib/commonjs/version.json +1 -1
  51. package/lib/module/components/Attachment/AudioAttachment.js +84 -209
  52. package/lib/module/components/Attachment/AudioAttachment.js.map +1 -1
  53. package/lib/module/components/Attachment/FileAttachmentGroup.js +8 -5
  54. package/lib/module/components/Attachment/FileAttachmentGroup.js.map +1 -1
  55. package/lib/module/components/AttachmentPicker/components/AttachmentPickerBottomSheetHandle.js +7 -3
  56. package/lib/module/components/AttachmentPicker/components/AttachmentPickerBottomSheetHandle.js.map +1 -1
  57. package/lib/module/components/Channel/Channel.js +20 -9
  58. package/lib/module/components/Channel/Channel.js.map +1 -1
  59. package/lib/module/components/Message/hooks/useMessageActionHandlers.js +4 -1
  60. package/lib/module/components/Message/hooks/useMessageActionHandlers.js.map +1 -1
  61. package/lib/module/components/MessageInput/MessageInput.js +2 -0
  62. package/lib/module/components/MessageInput/MessageInput.js.map +1 -1
  63. package/lib/module/components/MessageInput/components/AttachmentPreview/AudioAttachmentUploadPreview.js +9 -3
  64. package/lib/module/components/MessageInput/components/AttachmentPreview/AudioAttachmentUploadPreview.js.map +1 -1
  65. package/lib/module/components/MessageInput/components/AudioRecorder/AudioRecordingPreview.js +44 -8
  66. package/lib/module/components/MessageInput/components/AudioRecorder/AudioRecordingPreview.js.map +1 -1
  67. package/lib/module/components/MessageInput/hooks/useAudioController.js +5 -0
  68. package/lib/module/components/MessageInput/hooks/useAudioController.js.map +1 -1
  69. package/lib/module/components/MessageInput/hooks/useAudioPreviewManager.js.map +1 -1
  70. package/lib/module/components/ProgressControl/ProgressControl.js +25 -33
  71. package/lib/module/components/ProgressControl/ProgressControl.js.map +1 -1
  72. package/lib/module/components/ProgressControl/WaveProgressBar.js +21 -29
  73. package/lib/module/components/ProgressControl/WaveProgressBar.js.map +1 -1
  74. package/lib/module/contexts/audioPlayerContext/AudioPlayerContext.js +56 -0
  75. package/lib/module/contexts/audioPlayerContext/AudioPlayerContext.js.map +1 -0
  76. package/lib/module/contexts/index.js +11 -0
  77. package/lib/module/contexts/index.js.map +1 -1
  78. package/lib/module/contexts/themeContext/utils/theme.js +4 -0
  79. package/lib/module/contexts/themeContext/utils/theme.js.map +1 -1
  80. package/lib/module/hooks/index.js +11 -0
  81. package/lib/module/hooks/index.js.map +1 -1
  82. package/lib/module/hooks/useAudioPlayer.js +18 -25
  83. package/lib/module/hooks/useAudioPlayer.js.map +1 -1
  84. package/lib/module/hooks/useAudioPlayerControl.js +43 -0
  85. package/lib/module/hooks/useAudioPlayerControl.js.map +1 -0
  86. package/lib/module/hooks/useInAppNotificationsState.js +1 -1
  87. package/lib/module/i18n/es.json +1 -2
  88. package/lib/module/i18n/he.json +5 -5
  89. package/lib/module/i18n/ru.json +0 -5
  90. package/lib/module/index.js +4 -4
  91. package/lib/module/index.js.map +1 -1
  92. package/lib/module/native.js.map +1 -1
  93. package/lib/module/state-store/audio-player-pool.js +99 -0
  94. package/lib/module/state-store/audio-player-pool.js.map +1 -0
  95. package/lib/module/state-store/audio-player.js +373 -0
  96. package/lib/module/state-store/audio-player.js.map +1 -0
  97. package/lib/module/state-store/in-app-notifications-store.js.map +1 -0
  98. package/lib/module/state-store/index.js +37 -0
  99. package/lib/module/state-store/index.js.map +1 -0
  100. package/lib/module/version.json +1 -1
  101. package/lib/typescript/components/Attachment/AudioAttachment.d.ts +25 -5
  102. package/lib/typescript/components/Attachment/AudioAttachment.d.ts.map +1 -1
  103. package/lib/typescript/components/Attachment/FileAttachmentGroup.d.ts +2 -1
  104. package/lib/typescript/components/Attachment/FileAttachmentGroup.d.ts.map +1 -1
  105. package/lib/typescript/components/AttachmentPicker/components/AttachmentPickerBottomSheetHandle.d.ts.map +1 -1
  106. package/lib/typescript/components/Channel/Channel.d.ts +5 -0
  107. package/lib/typescript/components/Channel/Channel.d.ts.map +1 -1
  108. package/lib/typescript/components/Message/hooks/useMessageActionHandlers.d.ts.map +1 -1
  109. package/lib/typescript/components/MessageInput/MessageInput.d.ts.map +1 -1
  110. package/lib/typescript/components/MessageInput/components/AttachmentPreview/AudioAttachmentUploadPreview.d.ts +17 -0
  111. package/lib/typescript/components/MessageInput/components/AttachmentPreview/AudioAttachmentUploadPreview.d.ts.map +1 -1
  112. package/lib/typescript/components/MessageInput/components/AudioRecorder/AudioRecordingPreview.d.ts +18 -4
  113. package/lib/typescript/components/MessageInput/components/AudioRecorder/AudioRecordingPreview.d.ts.map +1 -1
  114. package/lib/typescript/components/MessageInput/hooks/useAudioController.d.ts +2 -0
  115. package/lib/typescript/components/MessageInput/hooks/useAudioController.d.ts.map +1 -1
  116. package/lib/typescript/components/MessageInput/hooks/useAudioPreviewManager.d.ts +2 -0
  117. package/lib/typescript/components/MessageInput/hooks/useAudioPreviewManager.d.ts.map +1 -1
  118. package/lib/typescript/components/ProgressControl/ProgressControl.d.ts +2 -0
  119. package/lib/typescript/components/ProgressControl/ProgressControl.d.ts.map +1 -1
  120. package/lib/typescript/components/ProgressControl/WaveProgressBar.d.ts.map +1 -1
  121. package/lib/typescript/contexts/audioPlayerContext/AudioPlayerContext.d.ts +15 -0
  122. package/lib/typescript/contexts/audioPlayerContext/AudioPlayerContext.d.ts.map +1 -0
  123. package/lib/typescript/contexts/index.d.ts +1 -0
  124. package/lib/typescript/contexts/index.d.ts.map +1 -1
  125. package/lib/typescript/contexts/themeContext/utils/theme.d.ts +4 -0
  126. package/lib/typescript/contexts/themeContext/utils/theme.d.ts.map +1 -1
  127. package/lib/typescript/hooks/index.d.ts +1 -0
  128. package/lib/typescript/hooks/index.d.ts.map +1 -1
  129. package/lib/typescript/hooks/useAudioPlayer.d.ts +3 -1
  130. package/lib/typescript/hooks/useAudioPlayer.d.ts.map +1 -1
  131. package/lib/typescript/hooks/useAudioPlayerControl.d.ts +18 -0
  132. package/lib/typescript/hooks/useAudioPlayerControl.d.ts.map +1 -0
  133. package/lib/typescript/i18n/es.json +1 -2
  134. package/lib/typescript/i18n/he.json +5 -5
  135. package/lib/typescript/i18n/ru.json +0 -5
  136. package/lib/typescript/index.d.ts +1 -1
  137. package/lib/typescript/index.d.ts.map +1 -1
  138. package/lib/typescript/native.d.ts +1 -0
  139. package/lib/typescript/native.d.ts.map +1 -1
  140. package/lib/typescript/state-store/audio-player-pool.d.ts +24 -0
  141. package/lib/typescript/state-store/audio-player-pool.d.ts.map +1 -0
  142. package/lib/typescript/state-store/audio-player.d.ts +62 -0
  143. package/lib/typescript/state-store/audio-player.d.ts.map +1 -0
  144. package/lib/typescript/state-store/in-app-notifications-store.d.ts.map +1 -0
  145. package/lib/typescript/state-store/index.d.ts +4 -0
  146. package/lib/typescript/state-store/index.d.ts.map +1 -0
  147. package/package.json +6 -5
  148. package/src/components/Attachment/AudioAttachment.tsx +118 -198
  149. package/src/components/Attachment/FileAttachmentGroup.tsx +35 -16
  150. package/src/components/AttachmentPicker/components/AttachmentPickerBottomSheetHandle.tsx +5 -2
  151. package/src/components/Channel/Channel.tsx +21 -4
  152. package/src/components/Message/hooks/useMessageActionHandlers.ts +3 -1
  153. package/src/components/MessageInput/MessageInput.tsx +6 -0
  154. package/src/components/MessageInput/components/AttachmentPreview/AudioAttachmentUploadPreview.tsx +29 -2
  155. package/src/components/MessageInput/components/AudioRecorder/AudioRecordingPreview.tsx +73 -9
  156. package/src/components/MessageInput/hooks/useAudioController.tsx +62 -1
  157. package/src/components/MessageInput/hooks/useAudioPreviewManager.tsx +28 -5
  158. package/src/components/ProgressControl/ProgressControl.tsx +45 -47
  159. package/src/components/ProgressControl/WaveProgressBar.tsx +37 -36
  160. package/src/contexts/audioPlayerContext/AudioPlayerContext.tsx +55 -0
  161. package/src/contexts/index.ts +1 -0
  162. package/src/contexts/themeContext/utils/theme.ts +8 -0
  163. package/src/hooks/index.ts +1 -0
  164. package/src/hooks/useAudioPlayer.ts +7 -8
  165. package/src/hooks/useAudioPlayerControl.ts +59 -0
  166. package/src/hooks/useInAppNotificationsState.ts +2 -2
  167. package/src/i18n/es.json +1 -2
  168. package/src/i18n/he.json +5 -5
  169. package/src/i18n/ru.json +0 -5
  170. package/src/index.ts +1 -1
  171. package/src/native.ts +1 -0
  172. package/src/state-store/audio-player-pool.ts +94 -0
  173. package/src/state-store/audio-player.ts +372 -0
  174. package/src/state-store/index.ts +3 -0
  175. package/src/version.json +1 -1
  176. package/lib/commonjs/store/in-app-notifications-store.js.map +0 -1
  177. package/lib/commonjs/store/index.js +0 -15
  178. package/lib/commonjs/store/index.js.map +0 -1
  179. package/lib/module/store/in-app-notifications-store.js.map +0 -1
  180. package/lib/module/store/index.js +0 -15
  181. package/lib/module/store/index.js.map +0 -1
  182. package/lib/typescript/store/in-app-notifications-store.d.ts.map +0 -1
  183. package/lib/typescript/store/index.d.ts +0 -2
  184. package/lib/typescript/store/index.d.ts.map +0 -1
  185. package/src/store/index.ts +0 -1
  186. /package/lib/commonjs/{store → state-store}/in-app-notifications-store.js +0 -0
  187. /package/lib/module/{store → state-store}/in-app-notifications-store.js +0 -0
  188. /package/lib/typescript/{store → state-store}/in-app-notifications-store.d.ts +0 -0
  189. /package/src/{store → state-store}/in-app-notifications-store.ts +0 -0
@@ -1,7 +1,12 @@
1
- import React, { useCallback, useEffect, useMemo, useState } from 'react';
1
+ import React, { useCallback, useMemo, useState } from 'react';
2
2
  import { Platform, StyleProp, StyleSheet, View, ViewStyle } from 'react-native';
3
3
  import { Gesture, GestureDetector } from 'react-native-gesture-handler';
4
- import Animated, { runOnJS, useAnimatedStyle, useSharedValue } from 'react-native-reanimated';
4
+ import Animated, {
5
+ runOnJS,
6
+ useAnimatedReaction,
7
+ useAnimatedStyle,
8
+ useSharedValue,
9
+ } from 'react-native-reanimated';
5
10
 
6
11
  import { useTheme } from '../../contexts/themeContext/ThemeContext';
7
12
  import { resampleWaveformData } from '../MessageInput/utils/audioSampling';
@@ -76,7 +81,6 @@ export const WaveProgressBar = React.memo(
76
81
  amplitudesCount = 70,
77
82
  filledColor,
78
83
  onEndDrag,
79
- onPlayPause,
80
84
  onProgressDrag,
81
85
  onStartDrag,
82
86
  progress,
@@ -98,9 +102,14 @@ export const WaveProgressBar = React.memo(
98
102
  [fullWidth],
99
103
  );
100
104
 
101
- useEffect(() => {
102
- waveFormNumberFromProgress(progress);
103
- }, [progress, waveFormNumberFromProgress]);
105
+ useAnimatedReaction(
106
+ () => progress,
107
+ (newProgress) => {
108
+ state.value = newProgress;
109
+ waveFormNumberFromProgress(newProgress);
110
+ },
111
+ [progress],
112
+ );
104
113
 
105
114
  const {
106
115
  theme: {
@@ -109,36 +118,28 @@ export const WaveProgressBar = React.memo(
109
118
  },
110
119
  } = useTheme();
111
120
 
112
- const pan = Gesture.Pan()
113
- .enabled(showProgressDrag)
114
- .maxPointers(1)
115
- .onStart((event) => {
116
- const currentProgress = (state.value + event.x) / fullWidth;
117
- state.value = Math.max(0, Math.min(currentProgress, 1));
118
- if (onStartDrag) {
119
- runOnJS(onStartDrag)(state.value);
120
- }
121
- if (onPlayPause) {
122
- runOnJS(onPlayPause)(true);
123
- }
124
- })
125
- .onUpdate((event) => {
126
- const currentProgress = (state.value + event.x) / fullWidth;
127
- state.value = Math.max(0, Math.min(currentProgress, 1));
128
- if (onProgressDrag) {
129
- runOnJS(onProgressDrag)(state.value);
130
- }
131
- })
132
- .onEnd((event) => {
133
- const currentProgress = (state.value + event.x) / fullWidth;
134
- state.value = Math.max(0, Math.min(currentProgress, 1));
135
- if (onEndDrag) {
136
- runOnJS(onEndDrag)(state.value);
137
- }
138
- if (onPlayPause) {
139
- runOnJS(onPlayPause)(false);
140
- }
141
- });
121
+ const pan = useMemo(
122
+ () =>
123
+ Gesture.Pan()
124
+ .enabled(showProgressDrag)
125
+ .maxPointers(1)
126
+ .onStart(() => {
127
+ if (onStartDrag) {
128
+ runOnJS(onStartDrag)(state.value);
129
+ }
130
+ })
131
+ .onUpdate((event) => {
132
+ const newProgress = Math.max(0, Math.min(event.x / fullWidth, 1));
133
+ state.value = newProgress;
134
+ waveFormNumberFromProgress(newProgress);
135
+ })
136
+ .onEnd(() => {
137
+ if (onEndDrag) {
138
+ runOnJS(onEndDrag)(state.value);
139
+ }
140
+ }),
141
+ [fullWidth, onEndDrag, onStartDrag, showProgressDrag, state, waveFormNumberFromProgress],
142
+ );
142
143
 
143
144
  const stringifiedWaveformData = waveformData.toString();
144
145
 
@@ -0,0 +1,55 @@
1
+ import React, { createContext, PropsWithChildren, useContext, useEffect, useMemo } from 'react';
2
+
3
+ import { useStateStore } from '../../hooks/useStateStore';
4
+ import { AudioPlayerPool, AudioPlayerPoolState } from '../../state-store/audio-player-pool';
5
+ import { DEFAULT_BASE_CONTEXT_VALUE } from '../utils/defaultBaseContextValue';
6
+
7
+ export type AudioPlayerContextProps = {
8
+ allowConcurrentAudioPlayback: boolean;
9
+ };
10
+
11
+ export type AudioPlayerContextValue = {
12
+ audioPlayerPool: AudioPlayerPool;
13
+ };
14
+
15
+ export const AudioPlayerContext = createContext<AudioPlayerContextValue>(
16
+ DEFAULT_BASE_CONTEXT_VALUE as AudioPlayerContextValue,
17
+ );
18
+
19
+ export const AudioPlayerProvider = ({
20
+ value,
21
+ children,
22
+ }: PropsWithChildren<{ value: AudioPlayerContextProps }>) => {
23
+ const { allowConcurrentAudioPlayback } = value;
24
+ const audioPlayerPool = useMemo(
25
+ () => new AudioPlayerPool({ allowConcurrentAudioPlayback }),
26
+ [allowConcurrentAudioPlayback],
27
+ );
28
+ const audioPlayerPoolContextValue = useMemo(() => ({ audioPlayerPool }), [audioPlayerPool]);
29
+
30
+ useEffect(
31
+ () => () => {
32
+ audioPlayerPool.clear();
33
+ },
34
+ [audioPlayerPool],
35
+ );
36
+
37
+ return (
38
+ <AudioPlayerContext.Provider value={audioPlayerPoolContextValue}>
39
+ {children}
40
+ </AudioPlayerContext.Provider>
41
+ );
42
+ };
43
+
44
+ export const useAudioPlayerContext = () => useContext(AudioPlayerContext);
45
+
46
+ const activeAudioPlayerSelector = ({ activeAudioPlayer }: AudioPlayerPoolState) => ({
47
+ activeAudioPlayer,
48
+ });
49
+
50
+ export const useActiveAudioPlayer = () => {
51
+ const { audioPlayerPool } = useContext(AudioPlayerContext);
52
+ const { activeAudioPlayer } =
53
+ useStateStore(audioPlayerPool.state, activeAudioPlayerSelector) ?? {};
54
+ return activeAudioPlayer;
55
+ };
@@ -28,3 +28,4 @@ export * from './typingContext/TypingContext';
28
28
  export * from './utils/getDisplayName';
29
29
  export * from './pollContext';
30
30
  export * from './liveLocationManagerContext';
31
+ export * from './audioPlayerContext/AudioPlayerContext';
@@ -105,6 +105,10 @@ export type Theme = {
105
105
  imageOverlaySelectedComponent: {
106
106
  check: ViewStyle;
107
107
  };
108
+ handle: {
109
+ container: ViewStyle;
110
+ indicator: ViewStyle;
111
+ };
108
112
  };
109
113
  attachmentSelectionBar: {
110
114
  container: ViewStyle;
@@ -896,6 +900,10 @@ export const defaultTheme: Theme = {
896
900
  errorButtonText: {},
897
901
  errorContainer: {},
898
902
  errorText: {},
903
+ handle: {
904
+ container: {},
905
+ indicator: {},
906
+ },
899
907
  image: {},
900
908
  imageOverlay: {},
901
909
  imageOverlaySelectedComponent: {
@@ -10,3 +10,4 @@ export * from './useQueryReminders';
10
10
  export * from './useClientNotifications';
11
11
  export * from './useInAppNotificationsState';
12
12
  export * from './useRAFCoalescedValue';
13
+ export * from './useAudioPlayerControl';
@@ -9,6 +9,8 @@ export type UseSoundPlayerProps = {
9
9
  /**
10
10
  * This hook is used to play, pause, seek and change audio speed.
11
11
  * It handles both Expo CLI and Native CLI.
12
+ *
13
+ * @deprecated This is deprecated and will be removed in the future.
12
14
  */
13
15
  export const useAudioPlayer = (props: UseSoundPlayerProps) => {
14
16
  const { soundRef } = props;
@@ -40,24 +42,21 @@ export const useAudioPlayer = (props: UseSoundPlayerProps) => {
40
42
  }, [isExpoCLI, soundRef]);
41
43
 
42
44
  const seekAudio = useCallback(
43
- async (currentTime: number) => {
45
+ async (currentTimeInSeconds: number = 0) => {
44
46
  if (isExpoCLI) {
45
- if (currentTime === 0) {
47
+ if (currentTimeInSeconds === 0) {
46
48
  // If currentTime is 0, we should replay the video from 0th position.
47
49
  if (soundRef.current?.replayAsync) {
48
- await soundRef.current.replayAsync({
49
- positionMillis: 0,
50
- shouldPlay: false,
51
- });
50
+ await soundRef.current.replayAsync({});
52
51
  }
53
52
  } else {
54
53
  if (soundRef.current?.setPositionAsync) {
55
- await soundRef.current.setPositionAsync(currentTime * 1000);
54
+ await soundRef.current.setPositionAsync(currentTimeInSeconds);
56
55
  }
57
56
  }
58
57
  } else {
59
58
  if (soundRef.current?.seek) {
60
- soundRef.current.seek(currentTime);
59
+ soundRef.current.seek(currentTimeInSeconds);
61
60
  }
62
61
  }
63
62
  },
@@ -0,0 +1,59 @@
1
+ import { useMemo } from 'react';
2
+
3
+ import { useAudioPlayerContext } from '../contexts/audioPlayerContext/AudioPlayerContext';
4
+ import { AudioPlayerOptions } from '../state-store/audio-player';
5
+
6
+ export type UseAudioPlayerControlProps = {
7
+ /**
8
+ * Identifier of the entity that requested the audio playback, e.g. message ID.
9
+ * Asset to specific audio player is a many-to-many relationship
10
+ * - one URL can be associated with multiple UI elements,
11
+ * - one UI element can display multiple audio sources.
12
+ * Therefore, the AudioPlayer ID is a combination of request:src.
13
+ *
14
+ * The requester string can take into consideration whether there are multiple instances of
15
+ * the same URL requested by the same requester (message has multiple attachments with the same asset URL).
16
+ * In reality the fact that one message has multiple attachments with the same asset URL
17
+ * could be considered a bad practice or a bug.
18
+ */
19
+ requester?: string;
20
+ } & Partial<AudioPlayerOptions>;
21
+
22
+ const makeAudioPlayerId = ({
23
+ requester,
24
+ src,
25
+ id,
26
+ }: {
27
+ src: string;
28
+ requester?: string;
29
+ id?: string;
30
+ }) => `${requester ?? 'requester-unknown'}:${src}:${id ?? ''}`;
31
+
32
+ export const useAudioPlayerControl = ({
33
+ duration,
34
+ mimeType,
35
+ playbackRates,
36
+ previewVoiceRecording,
37
+ requester = '',
38
+ type,
39
+ uri,
40
+ id: fileId,
41
+ }: UseAudioPlayerControlProps) => {
42
+ const { audioPlayerPool } = useAudioPlayerContext();
43
+ const id = makeAudioPlayerId({ id: fileId, requester, src: uri ?? '' });
44
+ const audioPlayer = useMemo(
45
+ () =>
46
+ audioPlayerPool?.getOrAddPlayer({
47
+ duration: duration ?? 0,
48
+ id,
49
+ mimeType: mimeType ?? '',
50
+ playbackRates,
51
+ previewVoiceRecording,
52
+ type: type ?? 'audio',
53
+ uri: uri ?? '',
54
+ }),
55
+ [audioPlayerPool, duration, id, mimeType, playbackRates, previewVoiceRecording, type, uri],
56
+ );
57
+
58
+ return audioPlayer;
59
+ };
@@ -3,12 +3,12 @@ import { Notification } from 'stream-chat';
3
3
  import { useStableCallback } from './useStableCallback';
4
4
  import { useStateStore } from './useStateStore';
5
5
 
6
- import type { InAppNotificationsState } from '../store/in-app-notifications-store';
6
+ import type { InAppNotificationsState } from '../state-store/in-app-notifications-store';
7
7
  import {
8
8
  closeInAppNotification,
9
9
  inAppNotificationsStore,
10
10
  openInAppNotification,
11
- } from '../store/in-app-notifications-store';
11
+ } from '../state-store/in-app-notifications-store';
12
12
 
13
13
  const selector = ({ notifications }: InAppNotificationsState) => ({
14
14
  notifications,
package/src/i18n/es.json CHANGED
@@ -129,18 +129,17 @@
129
129
  "Vote ended": "Votación finalizada",
130
130
  "You": "Tú",
131
131
  "You can't send messages in this channel": "No puedes enviar mensajes en este canal",
132
+ "duration/Location end at": "{{ milliseconds | durationFormatter(withSuffix: false) }}",
132
133
  "duration/Message reminder": "{{ milliseconds | durationFormatter(withSuffix: true) }}",
133
134
  "duration/Remind Me": "{{ milliseconds | durationFormatter(withSuffix: true) }}",
134
135
  "replied to": "respondió a",
135
136
  "timestamp/ChannelPreviewStatus": "{{ timestamp | timestampFormatter(calendar: true; calendarFormats: {\"lastDay\":\"[Ayer]\", \"lastWeek\":\"dddd\", \"nextDay\":\"[Mañana]\", \"nextWeek\":\"dddd [a las] LT\", \"sameDay\":\"LT\", \"sameElse\":\"L\"}) }}",
136
137
  "timestamp/ImageGalleryHeader": "{{ timestamp | timestampFormatter(calendar: true) }}",
137
138
  "timestamp/InlineDateSeparator": "{{ timestamp | timestampFormatter(calendar: true) }}",
138
- "timestamp/Location end at": "{{ milliseconds | durationFormatter(withSuffix: false) }}",
139
139
  "timestamp/MessageEditedTimestamp": "{{ timestamp | timestampFormatter(calendar: true) }}",
140
140
  "timestamp/MessageSystem": "{{ timestamp | timestampFormatter(calendar: true) }}",
141
141
  "timestamp/MessageTimestamp": "{{ timestamp | timestampFormatter(format: LT) }}",
142
142
  "timestamp/PollVote": "{{ timestamp | timestampFormatter(calendar: true; calendarFormats: {\"lastDay\":\"[Ayer]\", \"lastWeek\":\"dddd\", \"nextDay\":\"[Mañana]\", \"nextWeek\":\"dddd [a las] LT\", \"sameDay\":\"LT\", \"sameElse\":\"L\"}) }}",
143
- "timestamp/Remind me": "{{ milliseconds | durationFormatter(withSuffix: true) }}",
144
143
  "timestamp/ReminderNotification": "{{ timestamp | timestampFormatter(calendar: true) }}",
145
144
  "timestamp/StickyHeader": "{{ timestamp | timestampFormatter(calendar: true) }}",
146
145
  "timestamp/ThreadListItem": "{{ timestamp | timestampFormatter(calendar: true; calendarFormats: {\"lastDay\":\"[Ayer]\", \"lastWeek\":\"dddd\", \"nextDay\":\"[Mañana]\", \"nextWeek\":\"dddd [a las] LT\", \"sameDay\":\"LT\", \"sameElse\":\"L\"}) }}",
package/src/i18n/he.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
+ "+{{count}}_many": "+{{count}}",
2
3
  "+{{count}}_one": "+{{count}}",
3
4
  "+{{count}}_other": "+{{count}}",
4
- "+{{count}}_two": "+{{count}}",
5
5
  "1 Reply": "תגובה אחת",
6
6
  "1 Thread Reply": "תגובה אחת לשרשור",
7
7
  "Add a comment": "הוסף תגובה",
@@ -91,15 +91,15 @@
91
91
  "Resend": "שלח/י שוב",
92
92
  "SEND": "שלח",
93
93
  "Search": "חפש/י",
94
+ "See all {{count}} options_many": "הצג את כל {{count}} האפשרויות",
94
95
  "See all {{count}} options_one": "הצג את כל {{count}} האפשרויות",
95
96
  "See all {{count}} options_other": "הצג את כל {{count}} האפשרויות",
96
- "See all {{count}} options_two": "הצג את כל {{count}} האפשרויות",
97
97
  "Select More Photos": "בחר עוד תמונות",
98
98
  "Select one": "בחר אחת",
99
99
  "Select one or more": "בחר אחת או יותר",
100
+ "Select up to {{count}}_many": "בחר עד {{count}}",
100
101
  "Select up to {{count}}_one": "בחר עד {{count}}",
101
102
  "Select up to {{count}}_other": "בחר עד {{count}}",
102
- "Select up to {{count}}_two": "בחר עד {{count}}",
103
103
  "Send Anyway": "שלח בכל זאת",
104
104
  "Send a message": "שלח/י הודעה",
105
105
  "Sending links is not allowed in this conversation": "שליחת קישורים אינה מותרת בשיחה זו",
@@ -122,9 +122,9 @@
122
122
  "Update your comment": "עדכן את התגובה שלך",
123
123
  "Video": "וִידֵאוֹ",
124
124
  "View Results": "הצג תוצאות",
125
+ "View {{count}} comments_many": "הצג {{count}} תגובות",
125
126
  "View {{count}} comments_one": "הצג {{count}} תגובה",
126
127
  "View {{count}} comments_other": "הצג {{count}} תגובות",
127
- "View {{count}} comments_two": "הצג {{count}} תגובות",
128
128
  "Voice message": "הודעת קול",
129
129
  "Vote ended": "ההצבעה הסתיימה",
130
130
  "You": "את/ה",
@@ -148,8 +148,8 @@
148
148
  "{{ replyCount }} Replies": "{{ replyCount }} תגובות",
149
149
  "{{ replyCount }} Thread Replies": "{{ replyCount }} תגובות שרשור",
150
150
  "{{ user }} is typing": "{{ user }} מקליד/ה",
151
+ "{{count}} votes_many": "{{count}} הצבעות",
151
152
  "{{count}} votes_one": "{{count}} הצבעה",
152
153
  "{{count}} votes_other": "{{count}} הצבעות",
153
- "{{count}} votes_two": "{{count}} הצבעות",
154
154
  "🏙 Attachment...": "🏙 קובץ מצורף..."
155
155
  }
package/src/i18n/ru.json CHANGED
@@ -1,5 +1,4 @@
1
1
  {
2
- "+{{count}}_few": "+{{count}}",
3
2
  "+{{count}}_many": "+{{count}}",
4
3
  "+{{count}}_one": "+{{count}}",
5
4
  "+{{count}}_other": "+{{count}}",
@@ -92,14 +91,12 @@
92
91
  "Resend": "Отправить",
93
92
  "SEND": "ОТПРАВИТЬ",
94
93
  "Search": "Поиск",
95
- "See all {{count}} options_few": "Посмотреть все {{count}} вариантов",
96
94
  "See all {{count}} options_many": "Посмотреть все {{count}} вариантов",
97
95
  "See all {{count}} options_one": "Посмотреть все {{count}} вариант",
98
96
  "See all {{count}} options_other": "Посмотреть все {{count}} вариантов",
99
97
  "Select More Photos": "Выбрать больше фотографий",
100
98
  "Select one": "Выберите один",
101
99
  "Select one or more": "Выберите один или несколько",
102
- "Select up to {{count}}_few": "Выберите до {{count}}",
103
100
  "Select up to {{count}}_many": "Выберите до {{count}}",
104
101
  "Select up to {{count}}_one": "Выберите до {{count}}",
105
102
  "Select up to {{count}}_other": "Выберите до {{count}}",
@@ -125,7 +122,6 @@
125
122
  "Update your comment": "Обновить ваш комментарий",
126
123
  "Video": "видео",
127
124
  "View Results": "Посмотреть результаты",
128
- "View {{count}} comments_few": "Посмотреть {{count}} комментария",
129
125
  "View {{count}} comments_many": "Посмотреть {{count}} комментария",
130
126
  "View {{count}} comments_one": "Посмотреть {{count}} комментарий",
131
127
  "View {{count}} comments_other": "Посмотреть {{count}} комментария",
@@ -152,7 +148,6 @@
152
148
  "{{ replyCount }} Replies": "{{ replyCount }} Ответов",
153
149
  "{{ replyCount }} Thread Replies": "{{replyCount}} Ответы в темах",
154
150
  "{{ user }} is typing": "{{ user }} пишет",
155
- "{{count}} votes_few": "{{count}} голосов",
156
151
  "{{count}} votes_many": "{{count}} голосов",
157
152
  "{{count}} votes_one": "{{count}} голос",
158
153
  "{{count}} votes_other": "{{count}} голосов",
package/src/index.ts CHANGED
@@ -31,7 +31,7 @@ export { default as ptBRTranslations } from './i18n/pt-br.json';
31
31
  export { default as ruTranslations } from './i18n/ru.json';
32
32
  export { default as trTranslations } from './i18n/tr.json';
33
33
 
34
- export * from './store';
34
+ export * from './state-store';
35
35
  export { SqliteClient } from './store/SqliteClient';
36
36
  export { OfflineDB } from './store/OfflineDB';
37
37
  export { version } from './version.json';
package/src/native.ts CHANGED
@@ -227,6 +227,7 @@ export type AudioType = {
227
227
  stopRecording: () => Promise<void>;
228
228
  pausePlayer?: () => Promise<void>;
229
229
  resumePlayer?: () => Promise<void>;
230
+ seekToPlayer?: (positionInMillis: number) => Promise<void>;
230
231
  startPlayer?: (
231
232
  uri?: AudioRecordingReturnType,
232
233
  initialStatus?: Partial<AVPlaybackStatusToSet>,
@@ -0,0 +1,94 @@
1
+ import { StateStore } from 'stream-chat';
2
+
3
+ import { AudioPlayer, AudioPlayerOptions } from './audio-player';
4
+
5
+ export type AudioPlayerPoolOptions = {
6
+ allowConcurrentAudioPlayback: boolean;
7
+ };
8
+
9
+ export type AudioPlayerPoolState = {
10
+ activeAudioPlayer: AudioPlayer | null;
11
+ };
12
+
13
+ export class AudioPlayerPool {
14
+ pool: Map<string, AudioPlayer>;
15
+ allowConcurrentAudioPlayback: boolean;
16
+ state: StateStore<AudioPlayerPoolState> = new StateStore<AudioPlayerPoolState>({
17
+ activeAudioPlayer: null,
18
+ });
19
+
20
+ constructor({ allowConcurrentAudioPlayback }: AudioPlayerPoolOptions) {
21
+ this.pool = new Map<string, AudioPlayer>();
22
+ this.allowConcurrentAudioPlayback = allowConcurrentAudioPlayback ?? false;
23
+ }
24
+
25
+ get players() {
26
+ return Array.from(this.pool.values());
27
+ }
28
+
29
+ getOrAddPlayer(params: AudioPlayerOptions) {
30
+ const player = this.pool.get(params.id);
31
+ if (player) {
32
+ return player;
33
+ }
34
+ const newPlayer = new AudioPlayer(params);
35
+ newPlayer.pool = this;
36
+
37
+ this.pool.set(params.id, newPlayer);
38
+ return newPlayer;
39
+ }
40
+
41
+ setActivePlayer(activeAudioPlayer: AudioPlayer | null) {
42
+ this.state.partialNext({
43
+ activeAudioPlayer,
44
+ });
45
+ }
46
+
47
+ getActivePlayer() {
48
+ return this.state.getLatestValue().activeAudioPlayer;
49
+ }
50
+
51
+ removePlayer(id: string) {
52
+ const player = this.pool.get(id);
53
+ if (!player) return;
54
+ player.onRemove();
55
+ this.pool.delete(id);
56
+
57
+ if (this.getActivePlayer()?.id === id) {
58
+ this.setActivePlayer(null);
59
+ }
60
+ }
61
+
62
+ deregister(id: string) {
63
+ if (this.pool.has(id)) {
64
+ this.pool.delete(id);
65
+ }
66
+ }
67
+
68
+ clear() {
69
+ for (const player of this.pool.values()) {
70
+ this.removePlayer(player.id);
71
+ }
72
+ this.setActivePlayer(null);
73
+ }
74
+
75
+ requestPlay(id: string) {
76
+ if (this.allowConcurrentAudioPlayback) return;
77
+
78
+ if (this.getActivePlayer()?.id !== id) {
79
+ const currentPlayer = this.getActivePlayer();
80
+ if (currentPlayer && currentPlayer.isPlaying) {
81
+ currentPlayer.pause();
82
+ }
83
+ }
84
+
85
+ const activePlayer = this.pool.get(id);
86
+ if (activePlayer) {
87
+ this.setActivePlayer(activePlayer);
88
+ }
89
+ }
90
+
91
+ notifyPaused() {
92
+ this.setActivePlayer(null);
93
+ }
94
+ }