stream-chat-react-native-core 5.28.1 → 5.29.0-beta.1
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/Attachment.js +2 -2
- package/lib/commonjs/components/Attachment/Attachment.js.map +1 -1
- package/lib/commonjs/components/Attachment/AudioAttachment.js +247 -115
- package/lib/commonjs/components/Attachment/AudioAttachment.js.map +1 -1
- package/lib/commonjs/components/Attachment/FileAttachmentGroup.js +30 -50
- package/lib/commonjs/components/Attachment/FileAttachmentGroup.js.map +1 -1
- package/lib/commonjs/components/Attachment/VideoThumbnail.js +3 -3
- package/lib/commonjs/components/Attachment/VideoThumbnail.js.map +1 -1
- package/lib/commonjs/components/Channel/Channel.js +43 -1
- package/lib/commonjs/components/Channel/Channel.js.map +1 -1
- package/lib/commonjs/components/Channel/hooks/useCreateInputMessageInputContext.js +24 -0
- package/lib/commonjs/components/Channel/hooks/useCreateInputMessageInputContext.js.map +1 -1
- package/lib/commonjs/components/ImageGallery/components/ImageGalleryVideoControl.js +6 -6
- package/lib/commonjs/components/ImageGallery/components/ImageGalleryVideoControl.js.map +1 -1
- package/lib/commonjs/components/Message/Message.js +1 -1
- package/lib/commonjs/components/Message/Message.js.map +1 -1
- package/lib/commonjs/components/Message/MessageSimple/MessageContent.js +1 -1
- package/lib/commonjs/components/Message/MessageSimple/MessageContent.js.map +1 -1
- package/lib/commonjs/components/Message/MessageSimple/MessageSimple.js +1 -1
- package/lib/commonjs/components/Message/MessageSimple/MessageSimple.js.map +1 -1
- package/lib/commonjs/components/Message/hooks/useMessageActions.js +4 -2
- package/lib/commonjs/components/Message/hooks/useMessageActions.js.map +1 -1
- package/lib/commonjs/components/MessageInput/FileUploadPreview.js +55 -74
- package/lib/commonjs/components/MessageInput/FileUploadPreview.js.map +1 -1
- package/lib/commonjs/components/MessageInput/InputButtons.js +1 -1
- package/lib/commonjs/components/MessageInput/InputButtons.js.map +1 -1
- package/lib/commonjs/components/MessageInput/MessageInput.js +250 -43
- package/lib/commonjs/components/MessageInput/MessageInput.js.map +1 -1
- package/lib/commonjs/components/MessageInput/SendButton.js +9 -7
- package/lib/commonjs/components/MessageInput/SendButton.js.map +1 -1
- package/lib/commonjs/components/MessageInput/components/AudioRecorder/AudioRecorder.js +221 -0
- package/lib/commonjs/components/MessageInput/components/AudioRecorder/AudioRecorder.js.map +1 -0
- package/lib/commonjs/components/MessageInput/components/AudioRecorder/AudioRecordingButton.js +121 -0
- package/lib/commonjs/components/MessageInput/components/AudioRecorder/AudioRecordingButton.js.map +1 -0
- package/lib/commonjs/components/MessageInput/components/AudioRecorder/AudioRecordingInProgress.js +68 -0
- package/lib/commonjs/components/MessageInput/components/AudioRecorder/AudioRecordingInProgress.js.map +1 -0
- package/lib/commonjs/components/MessageInput/components/AudioRecorder/AudioRecordingLockIndicator.js +75 -0
- package/lib/commonjs/components/MessageInput/components/AudioRecorder/AudioRecordingLockIndicator.js.map +1 -0
- package/lib/commonjs/components/MessageInput/components/AudioRecorder/AudioRecordingPreview.js +87 -0
- package/lib/commonjs/components/MessageInput/components/AudioRecorder/AudioRecordingPreview.js.map +1 -0
- package/lib/commonjs/components/MessageInput/components/AudioRecorder/AudioRecordingWaveform.js +47 -0
- package/lib/commonjs/components/MessageInput/components/AudioRecorder/AudioRecordingWaveform.js.map +1 -0
- package/lib/commonjs/components/MessageInput/hooks/useAudioController.js +452 -0
- package/lib/commonjs/components/MessageInput/hooks/useAudioController.js.map +1 -0
- package/lib/commonjs/components/MessageInput/utils/audioSampling.js +91 -0
- package/lib/commonjs/components/MessageInput/utils/audioSampling.js.map +1 -0
- package/lib/commonjs/components/MessageInput/utils/normalizeAudioLevel.js +18 -0
- package/lib/commonjs/components/MessageInput/utils/normalizeAudioLevel.js.map +1 -0
- package/lib/commonjs/components/ProgressControl/ProgressControl.js +57 -40
- package/lib/commonjs/components/ProgressControl/ProgressControl.js.map +1 -1
- package/lib/commonjs/components/ProgressControl/WaveProgressBar.js +162 -0
- package/lib/commonjs/components/ProgressControl/WaveProgressBar.js.map +1 -0
- package/lib/commonjs/components/Reply/Reply.js +45 -20
- package/lib/commonjs/components/Reply/Reply.js.map +1 -1
- package/lib/commonjs/components/index.js +66 -0
- package/lib/commonjs/components/index.js.map +1 -1
- package/lib/commonjs/contexts/messageInputContext/MessageInputContext.js +23 -12
- package/lib/commonjs/contexts/messageInputContext/MessageInputContext.js.map +1 -1
- package/lib/commonjs/contexts/messageInputContext/hooks/useCreateMessageInputContext.js +24 -0
- package/lib/commonjs/contexts/messageInputContext/hooks/useCreateMessageInputContext.js.map +1 -1
- package/lib/commonjs/contexts/messageInputContext/hooks/useMessageDetailsForState.js +76 -28
- package/lib/commonjs/contexts/messageInputContext/hooks/useMessageDetailsForState.js.map +1 -1
- package/lib/commonjs/contexts/themeContext/utils/theme.js +62 -7
- package/lib/commonjs/contexts/themeContext/utils/theme.js.map +1 -1
- package/lib/commonjs/i18n/en.json +3 -1
- package/lib/commonjs/i18n/es.json +64 -62
- package/lib/commonjs/i18n/fr.json +64 -62
- package/lib/commonjs/i18n/he.json +64 -62
- package/lib/commonjs/i18n/hi.json +64 -62
- package/lib/commonjs/i18n/it.json +64 -62
- package/lib/commonjs/i18n/ja.json +64 -62
- package/lib/commonjs/i18n/ko.json +64 -62
- package/lib/commonjs/i18n/nl.json +64 -62
- package/lib/commonjs/i18n/pt-BR.json +64 -62
- package/lib/commonjs/i18n/ru.json +64 -62
- package/lib/commonjs/i18n/tr.json +64 -62
- package/lib/commonjs/icons/ArrowLeft.js +27 -0
- package/lib/commonjs/icons/ArrowLeft.js.map +1 -0
- package/lib/commonjs/icons/ArrowUp.js +26 -0
- package/lib/commonjs/icons/ArrowUp.js.map +1 -0
- package/lib/commonjs/icons/Audio.js +24 -24
- package/lib/commonjs/icons/Audio.js.map +1 -1
- package/lib/commonjs/icons/CircleStop.js +27 -0
- package/lib/commonjs/icons/CircleStop.js.map +1 -0
- package/lib/commonjs/icons/Delete.js +17 -6
- package/lib/commonjs/icons/Delete.js.map +1 -1
- package/lib/commonjs/icons/Lock.js +30 -0
- package/lib/commonjs/icons/Lock.js.map +1 -0
- package/lib/commonjs/icons/Mic.js +30 -0
- package/lib/commonjs/icons/Mic.js.map +1 -0
- package/lib/commonjs/icons/Pause.js +15 -20
- package/lib/commonjs/icons/Pause.js.map +1 -1
- package/lib/commonjs/icons/Play.js +18 -10
- package/lib/commonjs/icons/Play.js.map +1 -1
- package/lib/commonjs/icons/SendCheck.js +30 -0
- package/lib/commonjs/icons/SendCheck.js.map +1 -0
- package/lib/commonjs/icons/SendRight.js +24 -6
- package/lib/commonjs/icons/SendRight.js.map +1 -1
- package/lib/commonjs/icons/SendUp.js +24 -6
- package/lib/commonjs/icons/SendUp.js.map +1 -1
- package/lib/commonjs/icons/Stop.js +19 -0
- package/lib/commonjs/icons/Stop.js.map +1 -0
- package/lib/commonjs/icons/index.js +77 -0
- package/lib/commonjs/icons/index.js.map +1 -1
- package/lib/commonjs/native.js +10 -1
- package/lib/commonjs/native.js.map +1 -1
- package/lib/commonjs/utils/getTrimmedAttachmentTitle.js +11 -0
- package/lib/commonjs/utils/getTrimmedAttachmentTitle.js.map +1 -0
- package/lib/commonjs/version.json +1 -1
- package/lib/module/components/Attachment/Attachment.js +2 -2
- package/lib/module/components/Attachment/Attachment.js.map +1 -1
- package/lib/module/components/Attachment/AudioAttachment.js +247 -115
- package/lib/module/components/Attachment/AudioAttachment.js.map +1 -1
- package/lib/module/components/Attachment/FileAttachmentGroup.js +30 -50
- package/lib/module/components/Attachment/FileAttachmentGroup.js.map +1 -1
- package/lib/module/components/Attachment/VideoThumbnail.js +3 -3
- package/lib/module/components/Attachment/VideoThumbnail.js.map +1 -1
- package/lib/module/components/Channel/Channel.js +43 -1
- package/lib/module/components/Channel/Channel.js.map +1 -1
- package/lib/module/components/Channel/hooks/useCreateInputMessageInputContext.js +24 -0
- package/lib/module/components/Channel/hooks/useCreateInputMessageInputContext.js.map +1 -1
- package/lib/module/components/ImageGallery/components/ImageGalleryVideoControl.js +6 -6
- package/lib/module/components/ImageGallery/components/ImageGalleryVideoControl.js.map +1 -1
- package/lib/module/components/Message/Message.js +1 -1
- package/lib/module/components/Message/Message.js.map +1 -1
- package/lib/module/components/Message/MessageSimple/MessageContent.js +1 -1
- package/lib/module/components/Message/MessageSimple/MessageContent.js.map +1 -1
- package/lib/module/components/Message/MessageSimple/MessageSimple.js +1 -1
- package/lib/module/components/Message/MessageSimple/MessageSimple.js.map +1 -1
- package/lib/module/components/Message/hooks/useMessageActions.js +4 -2
- package/lib/module/components/Message/hooks/useMessageActions.js.map +1 -1
- package/lib/module/components/MessageInput/FileUploadPreview.js +55 -74
- package/lib/module/components/MessageInput/FileUploadPreview.js.map +1 -1
- package/lib/module/components/MessageInput/InputButtons.js +1 -1
- package/lib/module/components/MessageInput/InputButtons.js.map +1 -1
- package/lib/module/components/MessageInput/MessageInput.js +250 -43
- package/lib/module/components/MessageInput/MessageInput.js.map +1 -1
- package/lib/module/components/MessageInput/SendButton.js +9 -7
- package/lib/module/components/MessageInput/SendButton.js.map +1 -1
- package/lib/module/components/MessageInput/components/AudioRecorder/AudioRecorder.js +221 -0
- package/lib/module/components/MessageInput/components/AudioRecorder/AudioRecorder.js.map +1 -0
- package/lib/module/components/MessageInput/components/AudioRecorder/AudioRecordingButton.js +121 -0
- package/lib/module/components/MessageInput/components/AudioRecorder/AudioRecordingButton.js.map +1 -0
- package/lib/module/components/MessageInput/components/AudioRecorder/AudioRecordingInProgress.js +68 -0
- package/lib/module/components/MessageInput/components/AudioRecorder/AudioRecordingInProgress.js.map +1 -0
- package/lib/module/components/MessageInput/components/AudioRecorder/AudioRecordingLockIndicator.js +75 -0
- package/lib/module/components/MessageInput/components/AudioRecorder/AudioRecordingLockIndicator.js.map +1 -0
- package/lib/module/components/MessageInput/components/AudioRecorder/AudioRecordingPreview.js +87 -0
- package/lib/module/components/MessageInput/components/AudioRecorder/AudioRecordingPreview.js.map +1 -0
- package/lib/module/components/MessageInput/components/AudioRecorder/AudioRecordingWaveform.js +47 -0
- package/lib/module/components/MessageInput/components/AudioRecorder/AudioRecordingWaveform.js.map +1 -0
- package/lib/module/components/MessageInput/hooks/useAudioController.js +452 -0
- package/lib/module/components/MessageInput/hooks/useAudioController.js.map +1 -0
- package/lib/module/components/MessageInput/utils/audioSampling.js +91 -0
- package/lib/module/components/MessageInput/utils/audioSampling.js.map +1 -0
- package/lib/module/components/MessageInput/utils/normalizeAudioLevel.js +18 -0
- package/lib/module/components/MessageInput/utils/normalizeAudioLevel.js.map +1 -0
- package/lib/module/components/ProgressControl/ProgressControl.js +57 -40
- package/lib/module/components/ProgressControl/ProgressControl.js.map +1 -1
- package/lib/module/components/ProgressControl/WaveProgressBar.js +162 -0
- package/lib/module/components/ProgressControl/WaveProgressBar.js.map +1 -0
- package/lib/module/components/Reply/Reply.js +45 -20
- package/lib/module/components/Reply/Reply.js.map +1 -1
- package/lib/module/components/index.js +66 -0
- package/lib/module/components/index.js.map +1 -1
- package/lib/module/contexts/messageInputContext/MessageInputContext.js +23 -12
- package/lib/module/contexts/messageInputContext/MessageInputContext.js.map +1 -1
- package/lib/module/contexts/messageInputContext/hooks/useCreateMessageInputContext.js +24 -0
- package/lib/module/contexts/messageInputContext/hooks/useCreateMessageInputContext.js.map +1 -1
- package/lib/module/contexts/messageInputContext/hooks/useMessageDetailsForState.js +76 -28
- package/lib/module/contexts/messageInputContext/hooks/useMessageDetailsForState.js.map +1 -1
- package/lib/module/contexts/themeContext/utils/theme.js +62 -7
- package/lib/module/contexts/themeContext/utils/theme.js.map +1 -1
- package/lib/module/i18n/en.json +3 -1
- package/lib/module/i18n/es.json +64 -62
- package/lib/module/i18n/fr.json +64 -62
- package/lib/module/i18n/he.json +64 -62
- package/lib/module/i18n/hi.json +64 -62
- package/lib/module/i18n/it.json +64 -62
- package/lib/module/i18n/ja.json +64 -62
- package/lib/module/i18n/ko.json +64 -62
- package/lib/module/i18n/nl.json +64 -62
- package/lib/module/i18n/pt-BR.json +64 -62
- package/lib/module/i18n/ru.json +64 -62
- package/lib/module/i18n/tr.json +64 -62
- package/lib/module/icons/ArrowLeft.js +27 -0
- package/lib/module/icons/ArrowLeft.js.map +1 -0
- package/lib/module/icons/ArrowUp.js +26 -0
- package/lib/module/icons/ArrowUp.js.map +1 -0
- package/lib/module/icons/Audio.js +24 -24
- package/lib/module/icons/Audio.js.map +1 -1
- package/lib/module/icons/CircleStop.js +27 -0
- package/lib/module/icons/CircleStop.js.map +1 -0
- package/lib/module/icons/Delete.js +17 -6
- package/lib/module/icons/Delete.js.map +1 -1
- package/lib/module/icons/Lock.js +30 -0
- package/lib/module/icons/Lock.js.map +1 -0
- package/lib/module/icons/Mic.js +30 -0
- package/lib/module/icons/Mic.js.map +1 -0
- package/lib/module/icons/Pause.js +15 -20
- package/lib/module/icons/Pause.js.map +1 -1
- package/lib/module/icons/Play.js +18 -10
- package/lib/module/icons/Play.js.map +1 -1
- package/lib/module/icons/SendCheck.js +30 -0
- package/lib/module/icons/SendCheck.js.map +1 -0
- package/lib/module/icons/SendRight.js +24 -6
- package/lib/module/icons/SendRight.js.map +1 -1
- package/lib/module/icons/SendUp.js +24 -6
- package/lib/module/icons/SendUp.js.map +1 -1
- package/lib/module/icons/Stop.js +19 -0
- package/lib/module/icons/Stop.js.map +1 -0
- package/lib/module/icons/index.js +77 -0
- package/lib/module/icons/index.js.map +1 -1
- package/lib/module/native.js +10 -1
- package/lib/module/native.js.map +1 -1
- package/lib/module/utils/getTrimmedAttachmentTitle.js +11 -0
- package/lib/module/utils/getTrimmedAttachmentTitle.js.map +1 -0
- package/lib/module/version.json +1 -1
- package/lib/typescript/components/Attachment/Attachment.d.ts.map +1 -1
- package/lib/typescript/components/Attachment/AudioAttachment.d.ts +3 -8
- package/lib/typescript/components/Attachment/AudioAttachment.d.ts.map +1 -1
- package/lib/typescript/components/Attachment/FileAttachmentGroup.d.ts.map +1 -1
- package/lib/typescript/components/Channel/Channel.d.ts.map +1 -1
- package/lib/typescript/components/Channel/hooks/useCreateInputMessageInputContext.d.ts +15 -3
- package/lib/typescript/components/Channel/hooks/useCreateInputMessageInputContext.d.ts.map +1 -1
- package/lib/typescript/components/ImageGallery/components/ImageGalleryVideoControl.d.ts.map +1 -1
- package/lib/typescript/components/Message/MessageSimple/MessageContent.d.ts.map +1 -1
- package/lib/typescript/components/Message/MessageSimple/MessageSimple.d.ts.map +1 -1
- package/lib/typescript/components/MessageInput/FileUploadPreview.d.ts +1 -1
- package/lib/typescript/components/MessageInput/FileUploadPreview.d.ts.map +1 -1
- package/lib/typescript/components/MessageInput/InputButtons.d.ts.map +1 -1
- package/lib/typescript/components/MessageInput/MessageInput.d.ts +1 -1
- package/lib/typescript/components/MessageInput/MessageInput.d.ts.map +1 -1
- package/lib/typescript/components/MessageInput/SendButton.d.ts.map +1 -1
- package/lib/typescript/components/MessageInput/components/AudioRecorder/AudioRecorder.d.ts +51 -0
- package/lib/typescript/components/MessageInput/components/AudioRecorder/AudioRecorder.d.ts.map +1 -0
- package/lib/typescript/components/MessageInput/components/AudioRecorder/AudioRecordingButton.d.ts +43 -0
- package/lib/typescript/components/MessageInput/components/AudioRecorder/AudioRecordingButton.d.ts.map +1 -0
- package/lib/typescript/components/MessageInput/components/AudioRecorder/AudioRecordingInProgress.d.ts +29 -0
- package/lib/typescript/components/MessageInput/components/AudioRecorder/AudioRecordingInProgress.d.ts.map +1 -0
- package/lib/typescript/components/MessageInput/components/AudioRecorder/AudioRecordingLockIndicator.d.ts +22 -0
- package/lib/typescript/components/MessageInput/components/AudioRecorder/AudioRecordingLockIndicator.d.ts.map +1 -0
- package/lib/typescript/components/MessageInput/components/AudioRecorder/AudioRecordingPreview.d.ts +31 -0
- package/lib/typescript/components/MessageInput/components/AudioRecorder/AudioRecordingPreview.d.ts.map +1 -0
- package/lib/typescript/components/MessageInput/components/AudioRecorder/AudioRecordingWaveform.d.ts +19 -0
- package/lib/typescript/components/MessageInput/components/AudioRecorder/AudioRecordingWaveform.d.ts.map +1 -0
- package/lib/typescript/components/MessageInput/hooks/useAudioController.d.ts +28 -0
- package/lib/typescript/components/MessageInput/hooks/useAudioController.d.ts.map +1 -0
- package/lib/typescript/components/MessageInput/utils/audioSampling.d.ts +11 -0
- package/lib/typescript/components/MessageInput/utils/audioSampling.d.ts.map +1 -0
- package/lib/typescript/components/MessageInput/utils/normalizeAudioLevel.d.ts +5 -0
- package/lib/typescript/components/MessageInput/utils/normalizeAudioLevel.d.ts.map +1 -0
- package/lib/typescript/components/ProgressControl/ProgressControl.d.ts +2 -2
- package/lib/typescript/components/ProgressControl/ProgressControl.d.ts.map +1 -1
- package/lib/typescript/components/ProgressControl/WaveProgressBar.d.ts +11 -0
- package/lib/typescript/components/ProgressControl/WaveProgressBar.d.ts.map +1 -0
- package/lib/typescript/components/Reply/Reply.d.ts.map +1 -1
- package/lib/typescript/components/index.d.ts +6 -0
- package/lib/typescript/components/index.d.ts.map +1 -1
- package/lib/typescript/contexts/messageInputContext/MessageInputContext.d.ts +70 -4
- package/lib/typescript/contexts/messageInputContext/MessageInputContext.d.ts.map +1 -1
- package/lib/typescript/contexts/messageInputContext/hooks/useCreateMessageInputContext.d.ts +1 -1
- package/lib/typescript/contexts/messageInputContext/hooks/useCreateMessageInputContext.d.ts.map +1 -1
- package/lib/typescript/contexts/messageInputContext/hooks/useMessageDetailsForState.d.ts.map +1 -1
- package/lib/typescript/contexts/themeContext/utils/theme.d.ts +62 -7
- package/lib/typescript/contexts/themeContext/utils/theme.d.ts.map +1 -1
- package/lib/typescript/i18n/en.json +3 -1
- package/lib/typescript/i18n/es.json +64 -62
- package/lib/typescript/i18n/fr.json +64 -62
- package/lib/typescript/i18n/he.json +64 -62
- package/lib/typescript/i18n/hi.json +64 -62
- package/lib/typescript/i18n/it.json +64 -62
- package/lib/typescript/i18n/ja.json +64 -62
- package/lib/typescript/i18n/ko.json +64 -62
- package/lib/typescript/i18n/nl.json +64 -62
- package/lib/typescript/i18n/pt-BR.json +64 -62
- package/lib/typescript/i18n/ru.json +64 -62
- package/lib/typescript/i18n/tr.json +64 -62
- package/lib/typescript/icons/ArrowLeft.d.ts +8 -0
- package/lib/typescript/icons/ArrowLeft.d.ts.map +1 -0
- package/lib/typescript/icons/ArrowUp.d.ts +9 -0
- package/lib/typescript/icons/ArrowUp.d.ts.map +1 -0
- package/lib/typescript/icons/Audio.d.ts.map +1 -1
- package/lib/typescript/icons/CircleStop.d.ts +8 -0
- package/lib/typescript/icons/CircleStop.d.ts.map +1 -0
- package/lib/typescript/icons/Delete.d.ts +5 -1
- package/lib/typescript/icons/Delete.d.ts.map +1 -1
- package/lib/typescript/icons/Lock.d.ts +9 -0
- package/lib/typescript/icons/Lock.d.ts.map +1 -0
- package/lib/typescript/icons/Mic.d.ts +8 -0
- package/lib/typescript/icons/Mic.d.ts.map +1 -0
- package/lib/typescript/icons/Pause.d.ts +3 -1
- package/lib/typescript/icons/Pause.d.ts.map +1 -1
- package/lib/typescript/icons/Play.d.ts +3 -1
- package/lib/typescript/icons/Play.d.ts.map +1 -1
- package/lib/typescript/icons/SendCheck.d.ts +8 -0
- package/lib/typescript/icons/SendCheck.d.ts.map +1 -0
- package/lib/typescript/icons/SendRight.d.ts +5 -1
- package/lib/typescript/icons/SendRight.d.ts.map +1 -1
- package/lib/typescript/icons/SendUp.d.ts +5 -1
- package/lib/typescript/icons/SendUp.d.ts.map +1 -1
- package/lib/typescript/icons/Stop.d.ts +4 -0
- package/lib/typescript/icons/Stop.d.ts.map +1 -0
- package/lib/typescript/icons/index.d.ts +7 -0
- package/lib/typescript/icons/index.d.ts.map +1 -1
- package/lib/typescript/native.d.ts +49 -0
- package/lib/typescript/native.d.ts.map +1 -1
- package/lib/typescript/types/types.d.ts +6 -0
- package/lib/typescript/types/types.d.ts.map +1 -1
- package/lib/typescript/utils/Streami18n.d.ts +2 -0
- package/lib/typescript/utils/Streami18n.d.ts.map +1 -1
- package/lib/typescript/utils/getTrimmedAttachmentTitle.d.ts +2 -0
- package/lib/typescript/utils/getTrimmedAttachmentTitle.d.ts.map +1 -0
- package/package.json +1 -1
- package/src/components/Attachment/Attachment.tsx +7 -2
- package/src/components/Attachment/AudioAttachment.tsx +223 -119
- package/src/components/Attachment/FileAttachmentGroup.tsx +35 -55
- package/src/components/Attachment/VideoThumbnail.tsx +1 -1
- package/src/components/Channel/Channel.tsx +32 -0
- package/src/components/Channel/hooks/useCreateInputMessageInputContext.ts +24 -0
- package/src/components/ImageGallery/__tests__/ImageGallery.test.tsx +1 -1
- package/src/components/ImageGallery/__tests__/ImageGalleryVideoControl.test.tsx +2 -2
- package/src/components/ImageGallery/components/ImageGalleryVideoControl.tsx +2 -7
- package/src/components/Message/Message.tsx +1 -1
- package/src/components/Message/MessageSimple/MessageContent.tsx +2 -1
- package/src/components/Message/MessageSimple/MessageSimple.tsx +2 -1
- package/src/components/Message/hooks/useMessageActions.tsx +2 -2
- package/src/components/MessageInput/FileUploadPreview.tsx +67 -98
- package/src/components/MessageInput/InputButtons.tsx +2 -1
- package/src/components/MessageInput/MessageInput.tsx +320 -49
- package/src/components/MessageInput/SendButton.tsx +7 -3
- package/src/components/MessageInput/__tests__/MessageInput.test.js +0 -1
- package/src/components/MessageInput/__tests__/__snapshots__/SendButton.test.js.snap +132 -48
- package/src/components/MessageInput/components/AudioRecorder/AudioRecorder.tsx +313 -0
- package/src/components/MessageInput/components/AudioRecorder/AudioRecordingButton.tsx +192 -0
- package/src/components/MessageInput/components/AudioRecorder/AudioRecordingInProgress.tsx +114 -0
- package/src/components/MessageInput/components/AudioRecorder/AudioRecordingLockIndicator.tsx +85 -0
- package/src/components/MessageInput/components/AudioRecorder/AudioRecordingPreview.tsx +102 -0
- package/src/components/MessageInput/components/AudioRecorder/AudioRecordingWaveform.tsx +62 -0
- package/src/components/MessageInput/hooks/useAudioController.tsx +288 -0
- package/src/components/MessageInput/utils/audioSampling.ts +108 -0
- package/src/components/MessageInput/utils/normalizeAudioLevel.ts +20 -0
- package/src/components/ProgressControl/ProgressControl.tsx +69 -40
- package/src/components/ProgressControl/WaveProgressBar.tsx +180 -0
- package/src/components/Reply/Reply.tsx +89 -56
- package/src/components/Thread/__tests__/__snapshots__/Thread.test.js.snap +38 -20
- package/src/components/index.ts +6 -0
- package/src/contexts/messageInputContext/MessageInputContext.tsx +95 -10
- package/src/contexts/messageInputContext/hooks/useCreateMessageInputContext.ts +25 -0
- package/src/contexts/messageInputContext/hooks/useMessageDetailsForState.ts +80 -27
- package/src/contexts/themeContext/utils/theme.ts +111 -14
- package/src/i18n/en.json +3 -1
- package/src/i18n/es.json +64 -62
- package/src/i18n/fr.json +64 -62
- package/src/i18n/he.json +64 -62
- package/src/i18n/hi.json +64 -62
- package/src/i18n/it.json +64 -62
- package/src/i18n/ja.json +64 -62
- package/src/i18n/ko.json +64 -62
- package/src/i18n/nl.json +64 -62
- package/src/i18n/pt-BR.json +64 -62
- package/src/i18n/ru.json +64 -62
- package/src/i18n/tr.json +64 -62
- package/src/icons/ArrowLeft.tsx +18 -0
- package/src/icons/ArrowUp.tsx +19 -0
- package/src/icons/Audio.tsx +24 -24
- package/src/icons/CircleStop.tsx +18 -0
- package/src/icons/Delete.tsx +14 -8
- package/src/icons/Lock.tsx +22 -0
- package/src/icons/Mic.tsx +20 -0
- package/src/icons/Pause.tsx +12 -11
- package/src/icons/Play.tsx +9 -13
- package/src/icons/SendCheck.tsx +18 -0
- package/src/icons/SendRight.tsx +16 -7
- package/src/icons/SendUp.tsx +16 -7
- package/src/icons/Stop.tsx +12 -0
- package/src/icons/index.ts +7 -0
- package/src/native.ts +69 -0
- package/src/types/types.ts +6 -0
- package/src/utils/getTrimmedAttachmentTitle.ts +5 -0
- package/src/version.json +1 -1
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
import { useEffect, useRef, useState } from 'react';
|
|
2
|
+
|
|
3
|
+
import { Alert, Platform } from 'react-native';
|
|
4
|
+
|
|
5
|
+
import { useMessageInputContext } from '../../../contexts/messageInputContext/MessageInputContext';
|
|
6
|
+
import {
|
|
7
|
+
Audio,
|
|
8
|
+
AudioRecordingReturnType,
|
|
9
|
+
PlaybackStatus,
|
|
10
|
+
RecordingStatus,
|
|
11
|
+
Sound,
|
|
12
|
+
SoundReturnType,
|
|
13
|
+
triggerHaptic,
|
|
14
|
+
} from '../../../native';
|
|
15
|
+
import { File } from '../../../types/types';
|
|
16
|
+
import { resampleWaveformData } from '../utils/audioSampling';
|
|
17
|
+
import { normalizeAudioLevel } from '../utils/normalizeAudioLevel';
|
|
18
|
+
|
|
19
|
+
export type RecordingStatusStates = 'idle' | 'recording' | 'stopped';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* The hook that controls all the async audio core features including start/stop or recording, player, upload/delete of the recorded audio.
|
|
23
|
+
*/
|
|
24
|
+
export const useAudioController = () => {
|
|
25
|
+
const [micLocked, setMicLocked] = useState(false);
|
|
26
|
+
const [permissionsGranted, setPermissionsGranted] = useState(true);
|
|
27
|
+
const [paused, setPaused] = useState<boolean>(true);
|
|
28
|
+
const [position, setPosition] = useState<number>(0);
|
|
29
|
+
const [progress, setProgress] = useState<number>(0);
|
|
30
|
+
const [waveformData, setWaveformData] = useState<number[]>([]);
|
|
31
|
+
const [isScheduledForSubmit, setIsScheduleForSubmit] = useState(false);
|
|
32
|
+
const [recording, setRecording] = useState<AudioRecordingReturnType>(undefined);
|
|
33
|
+
const [recordingDuration, setRecordingDuration] = useState<number>(0);
|
|
34
|
+
const [recordingStatus, setRecordingStatus] = useState<RecordingStatusStates>('idle');
|
|
35
|
+
|
|
36
|
+
const { sendMessage, uploadNewFile } = useMessageInputContext();
|
|
37
|
+
|
|
38
|
+
// For playback support in Expo CLI apps
|
|
39
|
+
const soundRef = useRef<SoundReturnType | null>(null);
|
|
40
|
+
|
|
41
|
+
// Effect to stop the player when the component unmounts
|
|
42
|
+
useEffect(
|
|
43
|
+
() => () => {
|
|
44
|
+
stopVoicePlayer();
|
|
45
|
+
},
|
|
46
|
+
[],
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
useEffect(() => {
|
|
50
|
+
if (isScheduledForSubmit) {
|
|
51
|
+
sendMessage();
|
|
52
|
+
setIsScheduleForSubmit(false);
|
|
53
|
+
}
|
|
54
|
+
}, [isScheduledForSubmit, sendMessage]);
|
|
55
|
+
|
|
56
|
+
const onVoicePlayerProgressHandler = (currentPosition: number, playbackDuration: number) => {
|
|
57
|
+
const currentProgress = currentPosition / playbackDuration;
|
|
58
|
+
if (currentProgress === 1) {
|
|
59
|
+
setPaused(true);
|
|
60
|
+
setProgress(0);
|
|
61
|
+
} else {
|
|
62
|
+
setProgress(currentProgress);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const onVoicePlayerPlaybackStatusUpdate = (status: PlaybackStatus) => {
|
|
67
|
+
if (status.shouldPlay === undefined || status.shouldPlay === true) {
|
|
68
|
+
setPosition(status?.currentPosition || status?.positionMillis);
|
|
69
|
+
setRecordingDuration(status.duration || status.durationMillis);
|
|
70
|
+
|
|
71
|
+
if (status.didJustFinish) {
|
|
72
|
+
onVoicePlayerProgressHandler(status.durationMillis, status.durationMillis);
|
|
73
|
+
} else {
|
|
74
|
+
// For Native CLI
|
|
75
|
+
if (status.currentPosition && status.duration)
|
|
76
|
+
onVoicePlayerProgressHandler(status.currentPosition, status.duration);
|
|
77
|
+
// For Expo CLI
|
|
78
|
+
else if (status.positionMillis && status.durationMillis)
|
|
79
|
+
onVoicePlayerProgressHandler(status.positionMillis, status.durationMillis);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const onVoicePlayerPlayPause = async () => {
|
|
85
|
+
if (paused) {
|
|
86
|
+
if (progress === 0) await startVoicePlayer();
|
|
87
|
+
else {
|
|
88
|
+
// For Native CLI
|
|
89
|
+
if (Audio.resumePlayer) await Audio.resumePlayer();
|
|
90
|
+
// For Expo CLI
|
|
91
|
+
if (soundRef.current?.playAsync) await soundRef.current.playAsync();
|
|
92
|
+
}
|
|
93
|
+
} else {
|
|
94
|
+
// For Native CLI
|
|
95
|
+
if (Audio.pausePlayer) await Audio.pausePlayer();
|
|
96
|
+
// For Expo CLI
|
|
97
|
+
if (soundRef.current?.pauseAsync) await soundRef.current.pauseAsync();
|
|
98
|
+
}
|
|
99
|
+
setPaused(!paused);
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Function to start playing voice recording to preview it after recording.
|
|
104
|
+
*/
|
|
105
|
+
const startVoicePlayer = async () => {
|
|
106
|
+
if (!recording) return;
|
|
107
|
+
// For Native CLI
|
|
108
|
+
if (Audio.startPlayer)
|
|
109
|
+
await Audio.startPlayer(recording, {}, onVoicePlayerPlaybackStatusUpdate);
|
|
110
|
+
// For Expo CLI
|
|
111
|
+
if (recording && typeof recording !== 'string') {
|
|
112
|
+
const uri = recording.getURI();
|
|
113
|
+
if (uri) {
|
|
114
|
+
soundRef.current = await Sound.initializeSound(
|
|
115
|
+
{ uri },
|
|
116
|
+
{},
|
|
117
|
+
onVoicePlayerPlaybackStatusUpdate,
|
|
118
|
+
);
|
|
119
|
+
if (soundRef.current?.playAsync && soundRef.current.setProgressUpdateIntervalAsync) {
|
|
120
|
+
await soundRef.current.playAsync();
|
|
121
|
+
await soundRef.current.setProgressUpdateIntervalAsync(
|
|
122
|
+
Platform.OS === 'android' ? 100 : 60,
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Function to stop playing voice recording.
|
|
131
|
+
*/
|
|
132
|
+
const stopVoicePlayer = async () => {
|
|
133
|
+
// For Native CLI
|
|
134
|
+
if (Audio.stopPlayer) {
|
|
135
|
+
await Audio.stopPlayer();
|
|
136
|
+
}
|
|
137
|
+
// For Expo CLI
|
|
138
|
+
if (recording && typeof recording !== 'string') {
|
|
139
|
+
if (soundRef.current?.stopAsync && soundRef.current?.unloadAsync) {
|
|
140
|
+
await soundRef.current.stopAsync();
|
|
141
|
+
await soundRef.current?.unloadAsync();
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
const onRecordingStatusUpdate = (status: RecordingStatus) => {
|
|
147
|
+
if (status.isDoneRecording === true) {
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
setRecordingDuration(status?.currentPosition || status.durationMillis);
|
|
151
|
+
// For expo android the lower bound is -120 so we need to normalize according to it. The `status.currentMetering` is undefined for Expo CLI apps, so we can use it.
|
|
152
|
+
const lowerBound = Platform.OS === 'ios' || status.currentMetering ? -60 : -120;
|
|
153
|
+
const normalizedAudioLevel = normalizeAudioLevel(
|
|
154
|
+
status.currentMetering || status.metering,
|
|
155
|
+
lowerBound,
|
|
156
|
+
);
|
|
157
|
+
setWaveformData((prev) => [...prev, normalizedAudioLevel]);
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Function to start voice recording.
|
|
162
|
+
*/
|
|
163
|
+
const startVoiceRecording = async () => {
|
|
164
|
+
setRecordingStatus('recording');
|
|
165
|
+
const recordingInfo = await Audio.startRecording(
|
|
166
|
+
{
|
|
167
|
+
isMeteringEnabled: true,
|
|
168
|
+
},
|
|
169
|
+
onRecordingStatusUpdate,
|
|
170
|
+
);
|
|
171
|
+
const accessGranted = recordingInfo.accessGranted;
|
|
172
|
+
if (accessGranted) {
|
|
173
|
+
setPermissionsGranted(true);
|
|
174
|
+
const recording = recordingInfo.recording;
|
|
175
|
+
if (recording && typeof recording !== 'string') {
|
|
176
|
+
recording.setProgressUpdateInterval(Platform.OS === 'android' ? 100 : 60);
|
|
177
|
+
}
|
|
178
|
+
setRecording(recording);
|
|
179
|
+
await stopVoicePlayer();
|
|
180
|
+
} else {
|
|
181
|
+
setPermissionsGranted(false);
|
|
182
|
+
resetState();
|
|
183
|
+
Alert.alert('Please allow Audio permissions in settings.');
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Function to stop voice recording.
|
|
189
|
+
*/
|
|
190
|
+
const stopVoiceRecording = async () => {
|
|
191
|
+
if (recording) {
|
|
192
|
+
// For Expo CLI
|
|
193
|
+
if (typeof recording !== 'string') {
|
|
194
|
+
await recording.stopAndUnloadAsync();
|
|
195
|
+
await Audio.stopRecording();
|
|
196
|
+
}
|
|
197
|
+
// For RN CLI
|
|
198
|
+
else {
|
|
199
|
+
await Audio.stopRecording();
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
setRecordingStatus('stopped');
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Function to reset the state of the message input for async voice messages.
|
|
207
|
+
*/
|
|
208
|
+
const resetState = () => {
|
|
209
|
+
setRecording(undefined);
|
|
210
|
+
setRecordingStatus('idle');
|
|
211
|
+
setMicLocked(false);
|
|
212
|
+
setWaveformData([]);
|
|
213
|
+
setPaused(true);
|
|
214
|
+
setPosition(0);
|
|
215
|
+
setProgress(0);
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Function to delete voice recording.
|
|
220
|
+
*/
|
|
221
|
+
const deleteVoiceRecording = async () => {
|
|
222
|
+
if (recordingStatus === 'recording') {
|
|
223
|
+
await stopVoiceRecording();
|
|
224
|
+
}
|
|
225
|
+
if (!paused) {
|
|
226
|
+
await stopVoicePlayer();
|
|
227
|
+
}
|
|
228
|
+
resetState();
|
|
229
|
+
triggerHaptic('impactMedium');
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Function to upload or send voice recording.
|
|
234
|
+
* @param multiSendEnabled boolean
|
|
235
|
+
*/
|
|
236
|
+
const uploadVoiceRecording = async (multiSendEnabled: boolean) => {
|
|
237
|
+
if (!paused) {
|
|
238
|
+
await stopVoicePlayer();
|
|
239
|
+
}
|
|
240
|
+
if (recordingStatus === 'recording') {
|
|
241
|
+
await stopVoiceRecording();
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
const durationInSeconds = parseFloat((recordingDuration / 1000).toFixed(3));
|
|
245
|
+
|
|
246
|
+
const resampledWaveformData = resampleWaveformData(waveformData, 100);
|
|
247
|
+
|
|
248
|
+
const file: File = {
|
|
249
|
+
duration: durationInSeconds,
|
|
250
|
+
mimeType: 'audio/aac',
|
|
251
|
+
name: `audio_recording_${new Date().toISOString()}.aac`,
|
|
252
|
+
type: 'voiceRecording',
|
|
253
|
+
uri: typeof recording !== 'string' ? (recording?.getURI() as string) : (recording as string),
|
|
254
|
+
waveform_data: resampledWaveformData,
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
if (multiSendEnabled) {
|
|
258
|
+
await uploadNewFile(file);
|
|
259
|
+
} else {
|
|
260
|
+
// FIXME: cannot call handleSubmit() directly as the function has stale reference to file uploads
|
|
261
|
+
await uploadNewFile(file);
|
|
262
|
+
setIsScheduleForSubmit(true);
|
|
263
|
+
}
|
|
264
|
+
resetState();
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
return {
|
|
268
|
+
deleteVoiceRecording,
|
|
269
|
+
micLocked,
|
|
270
|
+
onVoicePlayerPlayPause,
|
|
271
|
+
paused,
|
|
272
|
+
permissionsGranted,
|
|
273
|
+
position,
|
|
274
|
+
progress,
|
|
275
|
+
recording,
|
|
276
|
+
recordingDuration,
|
|
277
|
+
recordingStatus,
|
|
278
|
+
setMicLocked,
|
|
279
|
+
setRecording,
|
|
280
|
+
setRecordingDuration,
|
|
281
|
+
setRecordingStatus,
|
|
282
|
+
setWaveformData,
|
|
283
|
+
startVoiceRecording,
|
|
284
|
+
stopVoiceRecording,
|
|
285
|
+
uploadVoiceRecording,
|
|
286
|
+
waveformData,
|
|
287
|
+
};
|
|
288
|
+
};
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
export const resampleWaveformData = (waveformData: number[], amplitudesCount: number) =>
|
|
2
|
+
waveformData.length === amplitudesCount
|
|
3
|
+
? waveformData
|
|
4
|
+
: waveformData.length > amplitudesCount
|
|
5
|
+
? downSample(waveformData, amplitudesCount)
|
|
6
|
+
: upSample(waveformData, amplitudesCount);
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The downSample function uses the Largest-Triangle-Three-Buckets (LTTB) algorithm.
|
|
10
|
+
* See the thesis Downsampling Time Series for Visual Representation by Sveinn Steinarsson for more (https://skemman.is/bitstream/1946/15343/3/SS_MSthesis.pdf)
|
|
11
|
+
* @param data
|
|
12
|
+
* @param targetOutputSize
|
|
13
|
+
*/
|
|
14
|
+
export function downSample(data: number[], targetOutputSize: number): number[] {
|
|
15
|
+
if (data.length <= targetOutputSize || targetOutputSize === 0) {
|
|
16
|
+
return data;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (targetOutputSize === 1) return [mean(data)];
|
|
20
|
+
|
|
21
|
+
const result: number[] = [];
|
|
22
|
+
// bucket size adjusted due to the fact that the first and the last item in the original data array is kept in target output
|
|
23
|
+
const bucketSize = (data.length - 2) / (targetOutputSize - 2);
|
|
24
|
+
let lastSelectedPointIndex = 0;
|
|
25
|
+
result.push(data[lastSelectedPointIndex]); // Always add the first point
|
|
26
|
+
let maxAreaPoint, maxArea, triangleArea;
|
|
27
|
+
|
|
28
|
+
for (let bucketIndex = 1; bucketIndex < targetOutputSize - 1; bucketIndex++) {
|
|
29
|
+
const previousBucketRefPoint = data[lastSelectedPointIndex];
|
|
30
|
+
const nextBucketMean = getNextBucketMean(data, bucketIndex, bucketSize);
|
|
31
|
+
|
|
32
|
+
const currentBucketStartIndex = Math.floor((bucketIndex - 1) * bucketSize) + 1;
|
|
33
|
+
const nextBucketStartIndex = Math.floor(bucketIndex * bucketSize) + 1;
|
|
34
|
+
const countUnitsBetweenAtoC = 1 + nextBucketStartIndex - currentBucketStartIndex;
|
|
35
|
+
|
|
36
|
+
maxArea = triangleArea = -1;
|
|
37
|
+
|
|
38
|
+
for (
|
|
39
|
+
let currentPointIndex = currentBucketStartIndex;
|
|
40
|
+
currentPointIndex < nextBucketStartIndex;
|
|
41
|
+
currentPointIndex++
|
|
42
|
+
) {
|
|
43
|
+
const countUnitsBetweenAtoB = Math.abs(currentPointIndex - currentBucketStartIndex) + 1;
|
|
44
|
+
const countUnitsBetweenBtoC = countUnitsBetweenAtoC - countUnitsBetweenAtoB;
|
|
45
|
+
const currentPointValue = data[currentPointIndex];
|
|
46
|
+
|
|
47
|
+
triangleArea = triangleAreaHeron(
|
|
48
|
+
triangleBase(Math.abs(previousBucketRefPoint - currentPointValue), countUnitsBetweenAtoB),
|
|
49
|
+
triangleBase(Math.abs(currentPointValue - nextBucketMean), countUnitsBetweenBtoC),
|
|
50
|
+
triangleBase(Math.abs(previousBucketRefPoint - nextBucketMean), countUnitsBetweenAtoC),
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
if (triangleArea > maxArea) {
|
|
54
|
+
maxArea = triangleArea;
|
|
55
|
+
maxAreaPoint = data[currentPointIndex];
|
|
56
|
+
lastSelectedPointIndex = currentPointIndex;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (typeof maxAreaPoint !== 'undefined') result.push(maxAreaPoint);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
result.push(data[data.length - 1]); // Always add the last point
|
|
64
|
+
|
|
65
|
+
return result;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const triangleAreaHeron = (a: number, b: number, c: number) => {
|
|
69
|
+
const s = (a + b + c) / 2;
|
|
70
|
+
return Math.sqrt(s * (s - a) * (s - b) * (s - c));
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const triangleBase = (a: number, b: number) => Math.sqrt(Math.pow(a, 2) + Math.pow(b, 2));
|
|
74
|
+
const mean = (values: number[]) => values.reduce((acc, value) => acc + value, 0) / values.length;
|
|
75
|
+
export const divMod = (num: number, divisor: number) => [Math.floor(num / divisor), num % divisor];
|
|
76
|
+
|
|
77
|
+
const getNextBucketMean = (data: number[], currentBucketIndex: number, bucketSize: number) => {
|
|
78
|
+
const nextBucketStartIndex = Math.floor(currentBucketIndex * bucketSize) + 1;
|
|
79
|
+
let nextNextBucketStartIndex = Math.floor((currentBucketIndex + 1) * bucketSize) + 1;
|
|
80
|
+
nextNextBucketStartIndex =
|
|
81
|
+
nextNextBucketStartIndex < data.length ? nextNextBucketStartIndex : data.length;
|
|
82
|
+
|
|
83
|
+
return mean(data.slice(nextBucketStartIndex, nextNextBucketStartIndex));
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
export const upSample = (values: number[], targetSize: number) => {
|
|
87
|
+
if (!values.length) {
|
|
88
|
+
console.warn('Cannot extend empty array of amplitudes.');
|
|
89
|
+
return values;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (values.length > targetSize) {
|
|
93
|
+
console.warn('Requested to extend the waveformData that is longer than the target list size');
|
|
94
|
+
return values;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (targetSize === values.length) return values;
|
|
98
|
+
|
|
99
|
+
// eslint-disable-next-line prefer-const
|
|
100
|
+
let [bucketSize, remainder] = divMod(targetSize, values.length);
|
|
101
|
+
const result: number[] = [];
|
|
102
|
+
|
|
103
|
+
for (let i = 0; i < values.length; i++) {
|
|
104
|
+
const extra = remainder && remainder-- ? 1 : 0;
|
|
105
|
+
result.push(...Array(bucketSize + extra).fill(values[i]));
|
|
106
|
+
}
|
|
107
|
+
return result;
|
|
108
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility function to normalize the audio level.
|
|
3
|
+
*/
|
|
4
|
+
export const normalizeAudioLevel = (value: number, lowerBound: number) => {
|
|
5
|
+
// For Native CLI, the lower bound is around -50
|
|
6
|
+
const upperBound = 0;
|
|
7
|
+
|
|
8
|
+
const delta = upperBound - lowerBound;
|
|
9
|
+
|
|
10
|
+
// In Native CLI Android, the value is undefined for loud audio
|
|
11
|
+
if (value === undefined) return 1;
|
|
12
|
+
|
|
13
|
+
if (value < lowerBound) {
|
|
14
|
+
return 0;
|
|
15
|
+
} else if (value >= upperBound) {
|
|
16
|
+
return 1;
|
|
17
|
+
} else {
|
|
18
|
+
return Math.abs((value - lowerBound) / delta);
|
|
19
|
+
}
|
|
20
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useEffect } from 'react';
|
|
2
|
-
import { StyleSheet, View } from 'react-native';
|
|
2
|
+
import { Dimensions, StyleSheet, View } from 'react-native';
|
|
3
3
|
import { PanGestureHandler } from 'react-native-gesture-handler';
|
|
4
4
|
import Animated, {
|
|
5
5
|
cancelAnimation,
|
|
@@ -14,66 +14,65 @@ import { useTheme } from '../../contexts/themeContext/ThemeContext';
|
|
|
14
14
|
export type ProgressControlProps = {
|
|
15
15
|
duration: number;
|
|
16
16
|
filledColor: string;
|
|
17
|
-
onPlayPause: (status?: boolean) => void;
|
|
18
17
|
progress: number;
|
|
19
18
|
testID: string;
|
|
20
|
-
width: number;
|
|
19
|
+
width: number | string;
|
|
20
|
+
onPlayPause?: (status?: boolean) => void;
|
|
21
21
|
onProgressDrag?: (progress: number) => void;
|
|
22
22
|
};
|
|
23
23
|
|
|
24
24
|
const height = 2;
|
|
25
|
-
const styles = StyleSheet.create({
|
|
26
|
-
containerStyle: {
|
|
27
|
-
borderRadius: 50,
|
|
28
|
-
height,
|
|
29
|
-
},
|
|
30
|
-
innerStyle: {
|
|
31
|
-
height,
|
|
32
|
-
},
|
|
33
|
-
progressControlThumbStyle: {
|
|
34
|
-
borderRadius: 5,
|
|
35
|
-
elevation: 6,
|
|
36
|
-
height: 20,
|
|
37
|
-
shadowOffset: {
|
|
38
|
-
height: 3,
|
|
39
|
-
width: 0,
|
|
40
|
-
},
|
|
41
|
-
shadowOpacity: 0.27,
|
|
42
|
-
shadowRadius: 4.65,
|
|
43
|
-
top: -11,
|
|
44
|
-
width: 5,
|
|
45
|
-
},
|
|
46
|
-
});
|
|
47
25
|
|
|
48
26
|
const ProgressControlThumb = () => {
|
|
49
27
|
const {
|
|
50
28
|
theme: {
|
|
51
|
-
colors: { black },
|
|
29
|
+
colors: { black, grey_dark, static_white },
|
|
52
30
|
},
|
|
53
31
|
} = useTheme();
|
|
54
32
|
return (
|
|
55
33
|
<View
|
|
56
|
-
style={[
|
|
34
|
+
style={[
|
|
35
|
+
styles.progressControlThumbStyle,
|
|
36
|
+
{ backgroundColor: static_white, borderColor: grey_dark, shadowColor: black },
|
|
37
|
+
]}
|
|
57
38
|
/>
|
|
58
39
|
);
|
|
59
40
|
};
|
|
60
41
|
|
|
61
42
|
export const ProgressControl = React.memo(
|
|
62
43
|
(props: ProgressControlProps) => {
|
|
63
|
-
const {
|
|
44
|
+
const {
|
|
45
|
+
duration,
|
|
46
|
+
filledColor: filledColorFromProp,
|
|
47
|
+
onPlayPause,
|
|
48
|
+
onProgressDrag,
|
|
49
|
+
progress,
|
|
50
|
+
testID,
|
|
51
|
+
width,
|
|
52
|
+
} = props;
|
|
53
|
+
const { width: windowWidth } = Dimensions.get('screen');
|
|
54
|
+
const widthInNumbers = width
|
|
55
|
+
? typeof width === 'string'
|
|
56
|
+
? (windowWidth * Number(width?.substring(0, width.length - 1))) / 100
|
|
57
|
+
: width
|
|
58
|
+
: 0;
|
|
64
59
|
const {
|
|
65
60
|
theme: {
|
|
66
61
|
colors: { grey_dark },
|
|
62
|
+
progressControl: { container, filledColor: filledColorFromTheme, filledStyles, thumb },
|
|
67
63
|
},
|
|
68
64
|
} = useTheme();
|
|
69
65
|
|
|
70
66
|
const state = useSharedValue(0);
|
|
71
67
|
const translateX = useSharedValue(0);
|
|
68
|
+
const filledColor = filledColorFromProp || filledColorFromTheme;
|
|
72
69
|
|
|
73
70
|
useEffect(() => {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
71
|
+
if (progress <= 1) {
|
|
72
|
+
state.value = progress * widthInNumbers;
|
|
73
|
+
translateX.value = progress * widthInNumbers;
|
|
74
|
+
}
|
|
75
|
+
}, [progress, widthInNumbers]);
|
|
77
76
|
|
|
78
77
|
const animatedStyles = useAnimatedStyle(() => ({
|
|
79
78
|
backgroundColor: filledColor,
|
|
@@ -88,33 +87,36 @@ export const ProgressControl = React.memo(
|
|
|
88
87
|
{
|
|
89
88
|
onActive: (event) => {
|
|
90
89
|
state.value = translateX.value + event.translationX;
|
|
91
|
-
if (state.value >
|
|
90
|
+
if (state.value > widthInNumbers) state.value = widthInNumbers;
|
|
92
91
|
else if (state.value < 0) state.value = 0;
|
|
93
92
|
},
|
|
94
93
|
onFinish: () => {
|
|
95
94
|
translateX.value = state.value;
|
|
96
|
-
const dragFinishLocationInSeconds = (state.value /
|
|
95
|
+
const dragFinishLocationInSeconds = (state.value / widthInNumbers) * duration;
|
|
97
96
|
if (onProgressDrag) runOnJS(onProgressDrag)(dragFinishLocationInSeconds);
|
|
98
|
-
runOnJS(onPlayPause)(false);
|
|
97
|
+
if (onPlayPause) runOnJS(onPlayPause)(false);
|
|
99
98
|
},
|
|
100
99
|
onStart: () => {
|
|
101
|
-
runOnJS(onPlayPause)(true);
|
|
100
|
+
if (onPlayPause) runOnJS(onPlayPause)(true);
|
|
102
101
|
cancelAnimation(translateX);
|
|
103
102
|
state.value = translateX.value;
|
|
104
103
|
},
|
|
105
104
|
},
|
|
106
|
-
[duration],
|
|
105
|
+
[duration, widthInNumbers],
|
|
107
106
|
);
|
|
107
|
+
|
|
108
108
|
return (
|
|
109
|
-
<View
|
|
110
|
-
|
|
109
|
+
<View
|
|
110
|
+
style={[styles.container, { backgroundColor: grey_dark, width: widthInNumbers }, container]}
|
|
111
|
+
>
|
|
112
|
+
<Animated.View style={[styles.filledStyle, animatedStyles, filledStyles]} />
|
|
111
113
|
|
|
112
114
|
<PanGestureHandler
|
|
113
115
|
maxPointers={1}
|
|
114
116
|
onGestureEvent={onProgressDrag ? onGestureEvent : undefined}
|
|
115
117
|
testID={testID}
|
|
116
118
|
>
|
|
117
|
-
<Animated.View style={[thumbStyles]}>
|
|
119
|
+
<Animated.View style={[thumbStyles, thumb]}>
|
|
118
120
|
{onProgressDrag && <ProgressControlThumb />}
|
|
119
121
|
</Animated.View>
|
|
120
122
|
</PanGestureHandler>
|
|
@@ -122,10 +124,37 @@ export const ProgressControl = React.memo(
|
|
|
122
124
|
);
|
|
123
125
|
},
|
|
124
126
|
(prevProps, nextProps) => {
|
|
125
|
-
if (
|
|
127
|
+
if (
|
|
128
|
+
prevProps.duration === nextProps.duration &&
|
|
129
|
+
prevProps.progress === nextProps.progress &&
|
|
130
|
+
prevProps.width === nextProps.width
|
|
131
|
+
)
|
|
126
132
|
return true;
|
|
127
133
|
else return false;
|
|
128
134
|
},
|
|
129
135
|
);
|
|
130
136
|
|
|
137
|
+
const styles = StyleSheet.create({
|
|
138
|
+
container: {
|
|
139
|
+
borderRadius: 50,
|
|
140
|
+
height,
|
|
141
|
+
},
|
|
142
|
+
filledStyle: {
|
|
143
|
+
height,
|
|
144
|
+
},
|
|
145
|
+
progressControlThumbStyle: {
|
|
146
|
+
borderRadius: 5,
|
|
147
|
+
borderWidth: 0.2,
|
|
148
|
+
elevation: 6,
|
|
149
|
+
height: 20,
|
|
150
|
+
shadowOffset: {
|
|
151
|
+
height: 3,
|
|
152
|
+
width: 0,
|
|
153
|
+
},
|
|
154
|
+
shadowOpacity: 0.27,
|
|
155
|
+
shadowRadius: 4.65,
|
|
156
|
+
top: -11,
|
|
157
|
+
width: 5,
|
|
158
|
+
},
|
|
159
|
+
});
|
|
131
160
|
ProgressControl.displayName = 'ProgressControl';
|