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.
- package/lib/commonjs/components/Attachment/AudioAttachment.js +84 -209
- package/lib/commonjs/components/Attachment/AudioAttachment.js.map +1 -1
- package/lib/commonjs/components/Attachment/FileAttachmentGroup.js +8 -5
- package/lib/commonjs/components/Attachment/FileAttachmentGroup.js.map +1 -1
- package/lib/commonjs/components/AttachmentPicker/components/AttachmentPickerBottomSheetHandle.js +7 -3
- package/lib/commonjs/components/AttachmentPicker/components/AttachmentPickerBottomSheetHandle.js.map +1 -1
- package/lib/commonjs/components/Channel/Channel.js +20 -9
- package/lib/commonjs/components/Channel/Channel.js.map +1 -1
- package/lib/commonjs/components/Message/hooks/useMessageActionHandlers.js +4 -1
- package/lib/commonjs/components/Message/hooks/useMessageActionHandlers.js.map +1 -1
- package/lib/commonjs/components/MessageInput/MessageInput.js +2 -0
- package/lib/commonjs/components/MessageInput/MessageInput.js.map +1 -1
- package/lib/commonjs/components/MessageInput/components/AttachmentPreview/AudioAttachmentUploadPreview.js +9 -3
- package/lib/commonjs/components/MessageInput/components/AttachmentPreview/AudioAttachmentUploadPreview.js.map +1 -1
- package/lib/commonjs/components/MessageInput/components/AudioRecorder/AudioRecordingPreview.js +44 -8
- package/lib/commonjs/components/MessageInput/components/AudioRecorder/AudioRecordingPreview.js.map +1 -1
- package/lib/commonjs/components/MessageInput/hooks/useAudioController.js +5 -0
- package/lib/commonjs/components/MessageInput/hooks/useAudioController.js.map +1 -1
- package/lib/commonjs/components/MessageInput/hooks/useAudioPreviewManager.js.map +1 -1
- package/lib/commonjs/components/ProgressControl/ProgressControl.js +25 -33
- package/lib/commonjs/components/ProgressControl/ProgressControl.js.map +1 -1
- package/lib/commonjs/components/ProgressControl/WaveProgressBar.js +21 -29
- package/lib/commonjs/components/ProgressControl/WaveProgressBar.js.map +1 -1
- package/lib/commonjs/contexts/audioPlayerContext/AudioPlayerContext.js +56 -0
- package/lib/commonjs/contexts/audioPlayerContext/AudioPlayerContext.js.map +1 -0
- package/lib/commonjs/contexts/index.js +11 -0
- package/lib/commonjs/contexts/index.js.map +1 -1
- package/lib/commonjs/contexts/themeContext/utils/theme.js +4 -0
- package/lib/commonjs/contexts/themeContext/utils/theme.js.map +1 -1
- package/lib/commonjs/hooks/index.js +11 -0
- package/lib/commonjs/hooks/index.js.map +1 -1
- package/lib/commonjs/hooks/useAudioPlayer.js +18 -25
- package/lib/commonjs/hooks/useAudioPlayer.js.map +1 -1
- package/lib/commonjs/hooks/useAudioPlayerControl.js +43 -0
- package/lib/commonjs/hooks/useAudioPlayerControl.js.map +1 -0
- package/lib/commonjs/hooks/useInAppNotificationsState.js +1 -1
- package/lib/commonjs/i18n/es.json +1 -2
- package/lib/commonjs/i18n/he.json +5 -5
- package/lib/commonjs/i18n/ru.json +0 -5
- package/lib/commonjs/index.js +4 -4
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/native.js.map +1 -1
- package/lib/commonjs/state-store/audio-player-pool.js +99 -0
- package/lib/commonjs/state-store/audio-player-pool.js.map +1 -0
- package/lib/commonjs/state-store/audio-player.js +373 -0
- package/lib/commonjs/state-store/audio-player.js.map +1 -0
- package/lib/commonjs/state-store/in-app-notifications-store.js.map +1 -0
- package/lib/commonjs/state-store/index.js +37 -0
- package/lib/commonjs/state-store/index.js.map +1 -0
- package/lib/commonjs/version.json +1 -1
- package/lib/module/components/Attachment/AudioAttachment.js +84 -209
- package/lib/module/components/Attachment/AudioAttachment.js.map +1 -1
- package/lib/module/components/Attachment/FileAttachmentGroup.js +8 -5
- package/lib/module/components/Attachment/FileAttachmentGroup.js.map +1 -1
- package/lib/module/components/AttachmentPicker/components/AttachmentPickerBottomSheetHandle.js +7 -3
- package/lib/module/components/AttachmentPicker/components/AttachmentPickerBottomSheetHandle.js.map +1 -1
- package/lib/module/components/Channel/Channel.js +20 -9
- package/lib/module/components/Channel/Channel.js.map +1 -1
- package/lib/module/components/Message/hooks/useMessageActionHandlers.js +4 -1
- package/lib/module/components/Message/hooks/useMessageActionHandlers.js.map +1 -1
- package/lib/module/components/MessageInput/MessageInput.js +2 -0
- package/lib/module/components/MessageInput/MessageInput.js.map +1 -1
- package/lib/module/components/MessageInput/components/AttachmentPreview/AudioAttachmentUploadPreview.js +9 -3
- package/lib/module/components/MessageInput/components/AttachmentPreview/AudioAttachmentUploadPreview.js.map +1 -1
- package/lib/module/components/MessageInput/components/AudioRecorder/AudioRecordingPreview.js +44 -8
- package/lib/module/components/MessageInput/components/AudioRecorder/AudioRecordingPreview.js.map +1 -1
- package/lib/module/components/MessageInput/hooks/useAudioController.js +5 -0
- package/lib/module/components/MessageInput/hooks/useAudioController.js.map +1 -1
- package/lib/module/components/MessageInput/hooks/useAudioPreviewManager.js.map +1 -1
- package/lib/module/components/ProgressControl/ProgressControl.js +25 -33
- package/lib/module/components/ProgressControl/ProgressControl.js.map +1 -1
- package/lib/module/components/ProgressControl/WaveProgressBar.js +21 -29
- package/lib/module/components/ProgressControl/WaveProgressBar.js.map +1 -1
- package/lib/module/contexts/audioPlayerContext/AudioPlayerContext.js +56 -0
- package/lib/module/contexts/audioPlayerContext/AudioPlayerContext.js.map +1 -0
- package/lib/module/contexts/index.js +11 -0
- package/lib/module/contexts/index.js.map +1 -1
- package/lib/module/contexts/themeContext/utils/theme.js +4 -0
- package/lib/module/contexts/themeContext/utils/theme.js.map +1 -1
- package/lib/module/hooks/index.js +11 -0
- package/lib/module/hooks/index.js.map +1 -1
- package/lib/module/hooks/useAudioPlayer.js +18 -25
- package/lib/module/hooks/useAudioPlayer.js.map +1 -1
- package/lib/module/hooks/useAudioPlayerControl.js +43 -0
- package/lib/module/hooks/useAudioPlayerControl.js.map +1 -0
- package/lib/module/hooks/useInAppNotificationsState.js +1 -1
- package/lib/module/i18n/es.json +1 -2
- package/lib/module/i18n/he.json +5 -5
- package/lib/module/i18n/ru.json +0 -5
- package/lib/module/index.js +4 -4
- package/lib/module/index.js.map +1 -1
- package/lib/module/native.js.map +1 -1
- package/lib/module/state-store/audio-player-pool.js +99 -0
- package/lib/module/state-store/audio-player-pool.js.map +1 -0
- package/lib/module/state-store/audio-player.js +373 -0
- package/lib/module/state-store/audio-player.js.map +1 -0
- package/lib/module/state-store/in-app-notifications-store.js.map +1 -0
- package/lib/module/state-store/index.js +37 -0
- package/lib/module/state-store/index.js.map +1 -0
- package/lib/module/version.json +1 -1
- package/lib/typescript/components/Attachment/AudioAttachment.d.ts +25 -5
- package/lib/typescript/components/Attachment/AudioAttachment.d.ts.map +1 -1
- package/lib/typescript/components/Attachment/FileAttachmentGroup.d.ts +2 -1
- package/lib/typescript/components/Attachment/FileAttachmentGroup.d.ts.map +1 -1
- package/lib/typescript/components/AttachmentPicker/components/AttachmentPickerBottomSheetHandle.d.ts.map +1 -1
- package/lib/typescript/components/Channel/Channel.d.ts +5 -0
- package/lib/typescript/components/Channel/Channel.d.ts.map +1 -1
- package/lib/typescript/components/Message/hooks/useMessageActionHandlers.d.ts.map +1 -1
- package/lib/typescript/components/MessageInput/MessageInput.d.ts.map +1 -1
- package/lib/typescript/components/MessageInput/components/AttachmentPreview/AudioAttachmentUploadPreview.d.ts +17 -0
- package/lib/typescript/components/MessageInput/components/AttachmentPreview/AudioAttachmentUploadPreview.d.ts.map +1 -1
- package/lib/typescript/components/MessageInput/components/AudioRecorder/AudioRecordingPreview.d.ts +18 -4
- package/lib/typescript/components/MessageInput/components/AudioRecorder/AudioRecordingPreview.d.ts.map +1 -1
- package/lib/typescript/components/MessageInput/hooks/useAudioController.d.ts +2 -0
- package/lib/typescript/components/MessageInput/hooks/useAudioController.d.ts.map +1 -1
- package/lib/typescript/components/MessageInput/hooks/useAudioPreviewManager.d.ts +2 -0
- package/lib/typescript/components/MessageInput/hooks/useAudioPreviewManager.d.ts.map +1 -1
- package/lib/typescript/components/ProgressControl/ProgressControl.d.ts +2 -0
- package/lib/typescript/components/ProgressControl/ProgressControl.d.ts.map +1 -1
- package/lib/typescript/components/ProgressControl/WaveProgressBar.d.ts.map +1 -1
- package/lib/typescript/contexts/audioPlayerContext/AudioPlayerContext.d.ts +15 -0
- package/lib/typescript/contexts/audioPlayerContext/AudioPlayerContext.d.ts.map +1 -0
- package/lib/typescript/contexts/index.d.ts +1 -0
- package/lib/typescript/contexts/index.d.ts.map +1 -1
- package/lib/typescript/contexts/themeContext/utils/theme.d.ts +4 -0
- package/lib/typescript/contexts/themeContext/utils/theme.d.ts.map +1 -1
- package/lib/typescript/hooks/index.d.ts +1 -0
- package/lib/typescript/hooks/index.d.ts.map +1 -1
- package/lib/typescript/hooks/useAudioPlayer.d.ts +3 -1
- package/lib/typescript/hooks/useAudioPlayer.d.ts.map +1 -1
- package/lib/typescript/hooks/useAudioPlayerControl.d.ts +18 -0
- package/lib/typescript/hooks/useAudioPlayerControl.d.ts.map +1 -0
- package/lib/typescript/i18n/es.json +1 -2
- package/lib/typescript/i18n/he.json +5 -5
- package/lib/typescript/i18n/ru.json +0 -5
- package/lib/typescript/index.d.ts +1 -1
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/native.d.ts +1 -0
- package/lib/typescript/native.d.ts.map +1 -1
- package/lib/typescript/state-store/audio-player-pool.d.ts +24 -0
- package/lib/typescript/state-store/audio-player-pool.d.ts.map +1 -0
- package/lib/typescript/state-store/audio-player.d.ts +62 -0
- package/lib/typescript/state-store/audio-player.d.ts.map +1 -0
- package/lib/typescript/state-store/in-app-notifications-store.d.ts.map +1 -0
- package/lib/typescript/state-store/index.d.ts +4 -0
- package/lib/typescript/state-store/index.d.ts.map +1 -0
- package/package.json +6 -5
- package/src/components/Attachment/AudioAttachment.tsx +118 -198
- package/src/components/Attachment/FileAttachmentGroup.tsx +35 -16
- package/src/components/AttachmentPicker/components/AttachmentPickerBottomSheetHandle.tsx +5 -2
- package/src/components/Channel/Channel.tsx +21 -4
- package/src/components/Message/hooks/useMessageActionHandlers.ts +3 -1
- package/src/components/MessageInput/MessageInput.tsx +6 -0
- package/src/components/MessageInput/components/AttachmentPreview/AudioAttachmentUploadPreview.tsx +29 -2
- package/src/components/MessageInput/components/AudioRecorder/AudioRecordingPreview.tsx +73 -9
- package/src/components/MessageInput/hooks/useAudioController.tsx +62 -1
- package/src/components/MessageInput/hooks/useAudioPreviewManager.tsx +28 -5
- package/src/components/ProgressControl/ProgressControl.tsx +45 -47
- package/src/components/ProgressControl/WaveProgressBar.tsx +37 -36
- package/src/contexts/audioPlayerContext/AudioPlayerContext.tsx +55 -0
- package/src/contexts/index.ts +1 -0
- package/src/contexts/themeContext/utils/theme.ts +8 -0
- package/src/hooks/index.ts +1 -0
- package/src/hooks/useAudioPlayer.ts +7 -8
- package/src/hooks/useAudioPlayerControl.ts +59 -0
- package/src/hooks/useInAppNotificationsState.ts +2 -2
- package/src/i18n/es.json +1 -2
- package/src/i18n/he.json +5 -5
- package/src/i18n/ru.json +0 -5
- package/src/index.ts +1 -1
- package/src/native.ts +1 -0
- package/src/state-store/audio-player-pool.ts +94 -0
- package/src/state-store/audio-player.ts +372 -0
- package/src/state-store/index.ts +3 -0
- package/src/version.json +1 -1
- package/lib/commonjs/store/in-app-notifications-store.js.map +0 -1
- package/lib/commonjs/store/index.js +0 -15
- package/lib/commonjs/store/index.js.map +0 -1
- package/lib/module/store/in-app-notifications-store.js.map +0 -1
- package/lib/module/store/index.js +0 -15
- package/lib/module/store/index.js.map +0 -1
- package/lib/typescript/store/in-app-notifications-store.d.ts.map +0 -1
- package/lib/typescript/store/index.d.ts +0 -2
- package/lib/typescript/store/index.d.ts.map +0 -1
- package/src/store/index.ts +0 -1
- /package/lib/commonjs/{store → state-store}/in-app-notifications-store.js +0 -0
- /package/lib/module/{store → state-store}/in-app-notifications-store.js +0 -0
- /package/lib/typescript/{store → state-store}/in-app-notifications-store.d.ts +0 -0
- /package/src/{store → state-store}/in-app-notifications-store.ts +0 -0
|
@@ -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.
|
|
4
|
+
"version": "8.11.0-beta.3",
|
|
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-
|
|
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
|
|
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 {
|
|
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 {
|
|
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 {
|
|
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<
|
|
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
|
-
|
|
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
|
-
|
|
56
|
-
onPlayPause,
|
|
57
|
-
onProgress,
|
|
94
|
+
message,
|
|
58
95
|
showSpeedSettings = false,
|
|
59
96
|
testID,
|
|
60
97
|
titleMaxLength,
|
|
98
|
+
isPreview = false,
|
|
61
99
|
} = props;
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
const
|
|
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
|
-
//
|
|
69
|
-
if (isVoiceRecording
|
|
70
|
-
|
|
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
|
|
79
|
-
|
|
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
|
-
|
|
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 =
|
|
102
|
-
|
|
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
|
-
|
|
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
|
|
130
|
-
|
|
161
|
+
const dragStart = () => {
|
|
162
|
+
audioPlayer.pause();
|
|
131
163
|
};
|
|
132
164
|
|
|
133
|
-
const
|
|
134
|
-
|
|
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
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
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
|
-
|
|
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
|
-
|
|
281
|
-
?
|
|
282
|
-
? dayjs.duration(
|
|
283
|
-
: dayjs.duration(
|
|
284
|
-
: dayjs.duration(
|
|
285
|
-
[
|
|
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
|
-
{
|
|
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
|
|
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={
|
|
267
|
+
progress={progress}
|
|
348
268
|
waveformData={item.waveform_data}
|
|
349
269
|
/>
|
|
350
270
|
) : (
|
|
351
271
|
<ProgressControl
|
|
352
|
-
duration={
|
|
272
|
+
duration={duration}
|
|
353
273
|
filledColor={accent_blue}
|
|
354
274
|
onEndDrag={dragEnd}
|
|
355
275
|
onProgressDrag={dragProgress}
|
|
356
276
|
onStartDrag={dragStart}
|
|
357
|
-
progress={
|
|
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={
|
|
371
|
-
rate={
|
|
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
|
-
{
|
|
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${
|
|
313
|
+
>{`x${currentPlaybackRate.toFixed(1)}`}</Text>
|
|
394
314
|
</Pressable>
|
|
395
315
|
)}
|
|
396
316
|
</View>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { useEffect, useState } from 'react';
|
|
2
2
|
import { StyleProp, StyleSheet, View, ViewStyle } from 'react-native';
|
|
3
3
|
|
|
4
|
-
import
|
|
4
|
+
import { Attachment, isAudioAttachment, isVoiceRecordingAttachment } from 'stream-chat';
|
|
5
5
|
|
|
6
6
|
import { Attachment as AttachmentDefault } from './Attachment';
|
|
7
7
|
|
|
@@ -17,11 +17,10 @@ import {
|
|
|
17
17
|
import { useTheme } from '../../contexts/themeContext/ThemeContext';
|
|
18
18
|
import { isSoundPackageAvailable } from '../../native';
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
export type FileAttachmentGroupPropsWithContext = Pick<MessageContextValue, 'files'> &
|
|
20
|
+
export type FileAttachmentGroupPropsWithContext = Pick<MessageContextValue, 'files' | 'message'> &
|
|
23
21
|
Pick<MessagesContextValue, 'Attachment' | 'AudioAttachment'> & {
|
|
24
22
|
/**
|
|
23
|
+
* @deprecated Use message instead
|
|
25
24
|
* The unique id for the message with file attachments
|
|
26
25
|
*/
|
|
27
26
|
messageId: string;
|
|
@@ -38,7 +37,8 @@ type FilesToDisplayType = Attachment & {
|
|
|
38
37
|
};
|
|
39
38
|
|
|
40
39
|
const FileAttachmentGroupWithContext = (props: FileAttachmentGroupPropsWithContext) => {
|
|
41
|
-
const { Attachment, AudioAttachment, files,
|
|
40
|
+
const { Attachment, AudioAttachment, files, message, styles: stylesProp = {} } = props;
|
|
41
|
+
|
|
42
42
|
const [filesToDisplay, setFilesToDisplay] = useState<FilesToDisplayType[]>(() =>
|
|
43
43
|
files.map((file) => ({ ...file, duration: file.duration || 0, paused: true, progress: 0 })),
|
|
44
44
|
);
|
|
@@ -49,7 +49,14 @@ const FileAttachmentGroupWithContext = (props: FileAttachmentGroupPropsWithConte
|
|
|
49
49
|
);
|
|
50
50
|
}, [files]);
|
|
51
51
|
|
|
52
|
-
|
|
52
|
+
/**
|
|
53
|
+
* Handler triggered when an audio is loaded in the message input. The initial state is defined for the audio here and the duration is set.
|
|
54
|
+
* @param index - The index of the audio
|
|
55
|
+
* @param duration - The duration of the audio
|
|
56
|
+
*
|
|
57
|
+
* @deprecated This is deprecated and will be removed in the future.
|
|
58
|
+
* FIXME: Remove this in the next major version.
|
|
59
|
+
*/
|
|
53
60
|
const onLoad = (index: string, duration: number) => {
|
|
54
61
|
setFilesToDisplay((prevFilesToDisplay) =>
|
|
55
62
|
prevFilesToDisplay.map((fileToDisplay, id) => ({
|
|
@@ -59,7 +66,14 @@ const FileAttachmentGroupWithContext = (props: FileAttachmentGroupPropsWithConte
|
|
|
59
66
|
);
|
|
60
67
|
};
|
|
61
68
|
|
|
62
|
-
|
|
69
|
+
/**
|
|
70
|
+
* Handler which is triggered when the audio progresses/ the thumb is dragged in the progress control. The progressed duration is set here.
|
|
71
|
+
* @param index - The index of the audio
|
|
72
|
+
* @param progress - The progress of the audio
|
|
73
|
+
*
|
|
74
|
+
* @deprecated This is deprecated and will be removed in the future.
|
|
75
|
+
* FIXME: Remove this in the next major version.
|
|
76
|
+
*/
|
|
63
77
|
const onProgress = (index: string, progress: number) => {
|
|
64
78
|
setFilesToDisplay((prevFilesToDisplay) =>
|
|
65
79
|
prevFilesToDisplay.map((filesToDisplay, id) => ({
|
|
@@ -69,7 +83,14 @@ const FileAttachmentGroupWithContext = (props: FileAttachmentGroupPropsWithConte
|
|
|
69
83
|
);
|
|
70
84
|
};
|
|
71
85
|
|
|
72
|
-
|
|
86
|
+
/**
|
|
87
|
+
* Handler which controls or sets the paused/played state of the audio.
|
|
88
|
+
* @param index - The index of the audio
|
|
89
|
+
* @param pausedStatus - The paused status of the audio
|
|
90
|
+
*
|
|
91
|
+
* @deprecated This is deprecated and will be removed in the future.
|
|
92
|
+
* FIXME: Remove this in the next major version.
|
|
93
|
+
*/
|
|
73
94
|
const onPlayPause = (index: string, pausedStatus?: boolean) => {
|
|
74
95
|
if (pausedStatus === false) {
|
|
75
96
|
// If the status is false we set the audio with the index as playing and the others as paused.
|
|
@@ -102,21 +123,18 @@ const FileAttachmentGroupWithContext = (props: FileAttachmentGroupPropsWithConte
|
|
|
102
123
|
<View style={[styles.container, container, stylesProp.container]}>
|
|
103
124
|
{filesToDisplay.map((file, index) => (
|
|
104
125
|
<View
|
|
105
|
-
key={`file-by-attachment-group-${
|
|
126
|
+
key={`file-by-attachment-group-${message.id}-${index}`}
|
|
106
127
|
style={[
|
|
107
128
|
{ paddingBottom: index !== files.length - 1 ? 4 : 0 },
|
|
108
129
|
stylesProp.attachmentContainer,
|
|
109
130
|
attachmentContainer,
|
|
110
131
|
]}
|
|
111
132
|
>
|
|
112
|
-
{(file
|
|
133
|
+
{(isAudioAttachment(file) || isVoiceRecordingAttachment(file)) &&
|
|
113
134
|
isSoundPackageAvailable() ? (
|
|
114
135
|
<AudioAttachment
|
|
115
|
-
item={{
|
|
116
|
-
|
|
117
|
-
id: index.toString(),
|
|
118
|
-
type: file.type,
|
|
119
|
-
}}
|
|
136
|
+
item={{ ...file, id: index.toString(), type: file.type }}
|
|
137
|
+
message={message}
|
|
120
138
|
onLoad={onLoad}
|
|
121
139
|
onPlayPause={onPlayPause}
|
|
122
140
|
onProgress={onProgress}
|
|
@@ -154,7 +172,7 @@ export type FileAttachmentGroupProps = Partial<
|
|
|
154
172
|
export const FileAttachmentGroup = (props: FileAttachmentGroupProps) => {
|
|
155
173
|
const { files: propFiles, messageId } = props;
|
|
156
174
|
|
|
157
|
-
const { files: contextFiles } = useMessageContext();
|
|
175
|
+
const { files: contextFiles, message } = useMessageContext();
|
|
158
176
|
|
|
159
177
|
const { Attachment = AttachmentDefault, AudioAttachment } = useMessagesContext();
|
|
160
178
|
|
|
@@ -170,6 +188,7 @@ export const FileAttachmentGroup = (props: FileAttachmentGroupProps) => {
|
|
|
170
188
|
Attachment,
|
|
171
189
|
AudioAttachment,
|
|
172
190
|
files,
|
|
191
|
+
message,
|
|
173
192
|
messageId,
|
|
174
193
|
}}
|
|
175
194
|
/>
|
|
@@ -24,6 +24,9 @@ type Props = {
|
|
|
24
24
|
export const AttachmentPickerBottomSheetHandle = ({ animatedIndex }: Props) => {
|
|
25
25
|
const {
|
|
26
26
|
theme: {
|
|
27
|
+
attachmentPicker: {
|
|
28
|
+
handle: { container, indicator },
|
|
29
|
+
},
|
|
27
30
|
colors: { black, white },
|
|
28
31
|
},
|
|
29
32
|
} = useTheme();
|
|
@@ -34,8 +37,8 @@ export const AttachmentPickerBottomSheetHandle = ({ animatedIndex }: Props) => {
|
|
|
34
37
|
}));
|
|
35
38
|
|
|
36
39
|
return (
|
|
37
|
-
<Animated.View style={[styles.container, { backgroundColor: white }, style]}>
|
|
38
|
-
<View style={[styles.handle, { backgroundColor: `${black}1A` }]} />
|
|
40
|
+
<Animated.View style={[styles.container, { backgroundColor: white }, style, container]}>
|
|
41
|
+
<View style={[styles.handle, { backgroundColor: `${black}1A` }, indicator]} />
|
|
39
42
|
{/* ^ 1A = 10% opacity */}
|
|
40
43
|
</Animated.View>
|
|
41
44
|
);
|