stream-chat-react-native-core 4.12.0-beta.1 → 4.12.0-beta.4
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/{MessageInput/AudioAttachmentUploadPreview.js → Attachment/AudioAttachment.js} +26 -23
- package/lib/commonjs/components/Attachment/AudioAttachment.js.map +1 -0
- package/lib/commonjs/components/Attachment/FileAttachmentGroup.js +113 -10
- package/lib/commonjs/components/Attachment/FileAttachmentGroup.js.map +1 -1
- package/lib/commonjs/components/Attachment/Gallery.js +22 -18
- package/lib/commonjs/components/Attachment/Gallery.js.map +1 -1
- package/lib/commonjs/components/Attachment/VideoThumbnail.js +12 -6
- package/lib/commonjs/components/Attachment/VideoThumbnail.js.map +1 -1
- package/lib/commonjs/components/Channel/Channel.js +5 -5
- package/lib/commonjs/components/Channel/Channel.js.map +1 -1
- package/lib/commonjs/components/Channel/hooks/useCreateInputMessageInputContext.js +2 -2
- package/lib/commonjs/components/Channel/hooks/useCreateInputMessageInputContext.js.map +1 -1
- package/lib/commonjs/components/ImageGallery/components/ImageGalleryVideoControl.js +11 -10
- package/lib/commonjs/components/ImageGallery/components/ImageGalleryVideoControl.js.map +1 -1
- package/lib/commonjs/components/Message/MessageSimple/utils/parseLinks.js +1 -1
- package/lib/commonjs/components/Message/MessageSimple/utils/parseLinks.js.map +1 -1
- package/lib/commonjs/components/Message/MessageSimple/utils/parseLinks.test.js +1 -1
- package/lib/commonjs/components/Message/MessageSimple/utils/parseLinks.test.js.map +1 -1
- package/lib/commonjs/components/MessageInput/FileUploadPreview.js +10 -31
- package/lib/commonjs/components/MessageInput/FileUploadPreview.js.map +1 -1
- package/lib/commonjs/components/index.js +13 -13
- package/lib/commonjs/components/index.js.map +1 -1
- package/lib/commonjs/contexts/messageInputContext/MessageInputContext.js +2 -2
- package/lib/commonjs/contexts/messageInputContext/MessageInputContext.js.map +1 -1
- package/lib/commonjs/contexts/messageInputContext/hooks/useCreateMessageInputContext.js +2 -2
- package/lib/commonjs/contexts/messageInputContext/hooks/useCreateMessageInputContext.js.map +1 -1
- package/lib/commonjs/contexts/themeContext/utils/theme.js +2 -2
- package/lib/commonjs/contexts/themeContext/utils/theme.js.map +1 -1
- package/lib/commonjs/version.json +1 -1
- package/lib/module/components/{MessageInput/AudioAttachmentUploadPreview.js → Attachment/AudioAttachment.js} +26 -23
- package/lib/module/components/Attachment/AudioAttachment.js.map +1 -0
- package/lib/module/components/Attachment/FileAttachmentGroup.js +113 -10
- package/lib/module/components/Attachment/FileAttachmentGroup.js.map +1 -1
- package/lib/module/components/Attachment/Gallery.js +22 -18
- package/lib/module/components/Attachment/Gallery.js.map +1 -1
- package/lib/module/components/Attachment/VideoThumbnail.js +12 -6
- package/lib/module/components/Attachment/VideoThumbnail.js.map +1 -1
- package/lib/module/components/Channel/Channel.js +5 -5
- package/lib/module/components/Channel/Channel.js.map +1 -1
- package/lib/module/components/Channel/hooks/useCreateInputMessageInputContext.js +2 -2
- package/lib/module/components/Channel/hooks/useCreateInputMessageInputContext.js.map +1 -1
- package/lib/module/components/ImageGallery/components/ImageGalleryVideoControl.js +11 -10
- package/lib/module/components/ImageGallery/components/ImageGalleryVideoControl.js.map +1 -1
- package/lib/module/components/Message/MessageSimple/utils/parseLinks.js +1 -1
- package/lib/module/components/Message/MessageSimple/utils/parseLinks.js.map +1 -1
- package/lib/module/components/Message/MessageSimple/utils/parseLinks.test.js +1 -1
- package/lib/module/components/Message/MessageSimple/utils/parseLinks.test.js.map +1 -1
- package/lib/module/components/MessageInput/FileUploadPreview.js +10 -31
- package/lib/module/components/MessageInput/FileUploadPreview.js.map +1 -1
- package/lib/module/components/index.js +13 -13
- package/lib/module/components/index.js.map +1 -1
- package/lib/module/contexts/messageInputContext/MessageInputContext.js +2 -2
- package/lib/module/contexts/messageInputContext/MessageInputContext.js.map +1 -1
- package/lib/module/contexts/messageInputContext/hooks/useCreateMessageInputContext.js +2 -2
- package/lib/module/contexts/messageInputContext/hooks/useCreateMessageInputContext.js.map +1 -1
- package/lib/module/contexts/themeContext/utils/theme.js +2 -2
- package/lib/module/contexts/themeContext/utils/theme.js.map +1 -1
- package/lib/module/version.json +1 -1
- package/lib/typescript/components/Attachment/AudioAttachment.d.ts +26 -0
- package/lib/typescript/components/Attachment/FileAttachmentGroup.d.ts +2 -1
- package/lib/typescript/components/Channel/hooks/useCreateInputMessageInputContext.d.ts +1 -1
- package/lib/typescript/components/MessageInput/FileUploadPreview.d.ts +1 -1
- package/lib/typescript/components/index.d.ts +1 -1
- package/lib/typescript/contexts/messageInputContext/MessageInputContext.d.ts +4 -4
- package/lib/typescript/contexts/messageInputContext/hooks/useCreateMessageInputContext.d.ts +1 -1
- package/lib/typescript/contexts/themeContext/utils/theme.d.ts +2 -2
- package/package.json +1 -1
- package/src/components/{MessageInput/AudioAttachmentUploadPreview.tsx → Attachment/AudioAttachment.tsx} +21 -26
- package/src/components/Attachment/FileAttachmentGroup.tsx +96 -7
- package/src/components/Attachment/Gallery.tsx +7 -1
- package/src/components/Attachment/VideoThumbnail.tsx +3 -2
- package/src/components/Channel/Channel.tsx +3 -3
- package/src/components/Channel/hooks/useCreateInputMessageInputContext.ts +2 -2
- package/src/components/ImageGallery/components/ImageGalleryVideoControl.tsx +12 -7
- package/src/components/Message/MessageSimple/__tests__/MessageContent.test.js +4 -2
- package/src/components/Message/MessageSimple/utils/parseLinks.test.ts +4 -0
- package/src/components/Message/MessageSimple/utils/parseLinks.ts +1 -1
- package/src/components/MessageInput/FileUploadPreview.tsx +8 -17
- package/src/components/MessageInput/__tests__/AudioAttachmentUploadPreviewExpo.test.tsx +4 -7
- package/src/components/MessageInput/__tests__/AudioAttachmentUploadPreviewNative.test.tsx +4 -7
- package/src/components/MessageInput/__tests__/FileUploadPreview.test.js +5 -5
- package/src/components/index.ts +1 -1
- package/src/contexts/messageInputContext/MessageInputContext.tsx +3 -5
- package/src/contexts/messageInputContext/hooks/useCreateMessageInputContext.ts +2 -2
- package/src/contexts/themeContext/utils/theme.ts +4 -4
- package/src/version.json +1 -1
- package/lib/commonjs/components/MessageInput/AudioAttachmentUploadPreview.js.map +0 -1
- package/lib/module/components/MessageInput/AudioAttachmentUploadPreview.js.map +0 -1
- package/lib/typescript/components/MessageInput/AudioAttachmentUploadPreview.d.ts +0 -26
|
@@ -1,17 +1,24 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { useEffect, useState } from 'react';
|
|
2
2
|
import { StyleProp, StyleSheet, View, ViewStyle } from 'react-native';
|
|
3
3
|
|
|
4
|
+
import type { Attachment } from 'stream-chat';
|
|
5
|
+
|
|
4
6
|
import { Attachment as AttachmentDefault } from './Attachment';
|
|
5
7
|
|
|
6
8
|
import {
|
|
7
9
|
MessageContextValue,
|
|
8
10
|
useMessageContext,
|
|
9
11
|
} from '../../contexts/messageContext/MessageContext';
|
|
12
|
+
import {
|
|
13
|
+
MessageInputContextValue,
|
|
14
|
+
useMessageInputContext,
|
|
15
|
+
} from '../../contexts/messageInputContext/MessageInputContext';
|
|
10
16
|
import {
|
|
11
17
|
MessagesContextValue,
|
|
12
18
|
useMessagesContext,
|
|
13
19
|
} from '../../contexts/messagesContext/MessagesContext';
|
|
14
20
|
import { useTheme } from '../../contexts/themeContext/ThemeContext';
|
|
21
|
+
import { isAudioPackageAvailable } from '../../native';
|
|
15
22
|
|
|
16
23
|
import type { DefaultStreamChatGenerics } from '../../types/types';
|
|
17
24
|
|
|
@@ -24,6 +31,7 @@ const styles = StyleSheet.create({
|
|
|
24
31
|
export type FileAttachmentGroupPropsWithContext<
|
|
25
32
|
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
|
|
26
33
|
> = Pick<MessageContextValue<StreamChatGenerics>, 'files'> &
|
|
34
|
+
Pick<MessageInputContextValue<StreamChatGenerics>, 'AudioAttachment'> &
|
|
27
35
|
Pick<MessagesContextValue<StreamChatGenerics>, 'Attachment'> & {
|
|
28
36
|
/**
|
|
29
37
|
* The unique id for the message with file attachments
|
|
@@ -35,12 +43,73 @@ export type FileAttachmentGroupPropsWithContext<
|
|
|
35
43
|
}>;
|
|
36
44
|
};
|
|
37
45
|
|
|
46
|
+
type FilesToDisplayType<
|
|
47
|
+
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
|
|
48
|
+
> = Attachment<StreamChatGenerics> & {
|
|
49
|
+
duration: number;
|
|
50
|
+
paused: boolean;
|
|
51
|
+
progress: number;
|
|
52
|
+
};
|
|
53
|
+
|
|
38
54
|
const FileAttachmentGroupWithContext = <
|
|
39
55
|
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
|
|
40
56
|
>(
|
|
41
57
|
props: FileAttachmentGroupPropsWithContext<StreamChatGenerics>,
|
|
42
58
|
) => {
|
|
43
|
-
const { Attachment, files, messageId, styles: stylesProp = {} } = props;
|
|
59
|
+
const { Attachment, AudioAttachment, files, messageId, styles: stylesProp = {} } = props;
|
|
60
|
+
const [filesToDisplay, setFilesToDisplay] = useState<FilesToDisplayType[]>([]);
|
|
61
|
+
|
|
62
|
+
useEffect(() => {
|
|
63
|
+
setFilesToDisplay(files.map((file) => ({ ...file, duration: 0, paused: true, progress: 0 })));
|
|
64
|
+
}, [files]);
|
|
65
|
+
|
|
66
|
+
// 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.
|
|
67
|
+
const onLoad = (index: string, duration: number) => {
|
|
68
|
+
setFilesToDisplay((prevFilesToDisplay) =>
|
|
69
|
+
prevFilesToDisplay.map((fileToDisplay, id) => ({
|
|
70
|
+
...fileToDisplay,
|
|
71
|
+
duration: id.toString() === index ? duration : fileToDisplay.duration,
|
|
72
|
+
})),
|
|
73
|
+
);
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
// The handler which is triggered when the audio progresses/ the thumb is dragged in the progress control. The progressed duration is set here.
|
|
77
|
+
const onProgress = (index: string, currentTime?: number, hasEnd?: boolean) => {
|
|
78
|
+
setFilesToDisplay((prevFileUploads) =>
|
|
79
|
+
prevFileUploads.map((fileUpload, id) => ({
|
|
80
|
+
...fileUpload,
|
|
81
|
+
progress:
|
|
82
|
+
id.toString() === index
|
|
83
|
+
? hasEnd
|
|
84
|
+
? 1
|
|
85
|
+
: currentTime
|
|
86
|
+
? currentTime / (fileUpload.duration as number)
|
|
87
|
+
: 0
|
|
88
|
+
: fileUpload.progress,
|
|
89
|
+
})),
|
|
90
|
+
);
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
// The handler which controls or sets the paused/played state of the audio.
|
|
94
|
+
const onPlayPause = (index: string, pausedStatus?: boolean) => {
|
|
95
|
+
if (pausedStatus === false) {
|
|
96
|
+
// If the status is false we set the audio with the index as playing and the others as paused.
|
|
97
|
+
setFilesToDisplay((prevFileUploads) =>
|
|
98
|
+
prevFileUploads.map((fileUpload, id) => ({
|
|
99
|
+
...fileUpload,
|
|
100
|
+
paused: id.toString() === index ? false : true,
|
|
101
|
+
})),
|
|
102
|
+
);
|
|
103
|
+
} else {
|
|
104
|
+
// If the status is true we simply set all the audio's paused state as true.
|
|
105
|
+
setFilesToDisplay((prevFileUploads) =>
|
|
106
|
+
prevFileUploads.map((fileUpload) => ({
|
|
107
|
+
...fileUpload,
|
|
108
|
+
paused: true,
|
|
109
|
+
})),
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
};
|
|
44
113
|
|
|
45
114
|
const {
|
|
46
115
|
theme: {
|
|
@@ -52,7 +121,7 @@ const FileAttachmentGroupWithContext = <
|
|
|
52
121
|
|
|
53
122
|
return (
|
|
54
123
|
<View style={[styles.container, container, stylesProp.container]}>
|
|
55
|
-
{
|
|
124
|
+
{filesToDisplay.map((file, index) => (
|
|
56
125
|
<View
|
|
57
126
|
key={`${messageId}-${index}`}
|
|
58
127
|
style={[
|
|
@@ -60,7 +129,26 @@ const FileAttachmentGroupWithContext = <
|
|
|
60
129
|
stylesProp.attachmentContainer,
|
|
61
130
|
]}
|
|
62
131
|
>
|
|
63
|
-
|
|
132
|
+
{file.type === 'audio' && isAudioPackageAvailable() ? (
|
|
133
|
+
<View accessibilityLabel='audio-attachment-preview'>
|
|
134
|
+
<AudioAttachment
|
|
135
|
+
index={index}
|
|
136
|
+
item={{
|
|
137
|
+
duration: file.duration,
|
|
138
|
+
file: { name: file.title as string, uri: file.asset_url },
|
|
139
|
+
id: index.toString(),
|
|
140
|
+
paused: file.paused,
|
|
141
|
+
progress: file.progress,
|
|
142
|
+
}}
|
|
143
|
+
onLoad={onLoad}
|
|
144
|
+
onPlayPause={onPlayPause}
|
|
145
|
+
onProgress={onProgress}
|
|
146
|
+
testID='audio-attachment-preview'
|
|
147
|
+
/>
|
|
148
|
+
</View>
|
|
149
|
+
) : (
|
|
150
|
+
<Attachment attachment={file} />
|
|
151
|
+
)}
|
|
64
152
|
</View>
|
|
65
153
|
))}
|
|
66
154
|
</View>
|
|
@@ -74,9 +162,7 @@ const areEqual = <StreamChatGenerics extends DefaultStreamChatGenerics = Default
|
|
|
74
162
|
const { files: prevFiles } = prevProps;
|
|
75
163
|
const { files: nextFiles } = nextProps;
|
|
76
164
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
return filesEqual;
|
|
165
|
+
return prevFiles.length === nextFiles.length;
|
|
80
166
|
};
|
|
81
167
|
|
|
82
168
|
const MemoizedFileAttachmentGroup = React.memo(
|
|
@@ -100,6 +186,8 @@ export const FileAttachmentGroup = <
|
|
|
100
186
|
|
|
101
187
|
const { Attachment = AttachmentDefault } = useMessagesContext<StreamChatGenerics>();
|
|
102
188
|
|
|
189
|
+
const { AudioAttachment } = useMessageInputContext<StreamChatGenerics>();
|
|
190
|
+
|
|
103
191
|
const files = propFiles || contextFiles;
|
|
104
192
|
|
|
105
193
|
if (!files.length) return null;
|
|
@@ -108,6 +196,7 @@ export const FileAttachmentGroup = <
|
|
|
108
196
|
<MemoizedFileAttachmentGroup
|
|
109
197
|
{...{
|
|
110
198
|
Attachment,
|
|
199
|
+
AudioAttachment,
|
|
111
200
|
files,
|
|
112
201
|
messageId,
|
|
113
202
|
}}
|
|
@@ -62,6 +62,12 @@ const styles = StyleSheet.create({
|
|
|
62
62
|
left: 4,
|
|
63
63
|
position: 'absolute',
|
|
64
64
|
},
|
|
65
|
+
imageLoadingIndicatorContainer: {
|
|
66
|
+
height: '100%',
|
|
67
|
+
justifyContent: 'center',
|
|
68
|
+
position: 'absolute',
|
|
69
|
+
width: '100%',
|
|
70
|
+
},
|
|
65
71
|
imageLoadingIndicatorStyle: {
|
|
66
72
|
alignItems: 'center',
|
|
67
73
|
justifyContent: 'center',
|
|
@@ -490,7 +496,7 @@ const GalleryImageThumbnail = <
|
|
|
490
496
|
uri={thumbnail.url}
|
|
491
497
|
/>
|
|
492
498
|
{isLoadingImage && (
|
|
493
|
-
<View style={
|
|
499
|
+
<View style={[styles.imageLoadingIndicatorContainer]}>
|
|
494
500
|
<ImageLoadingIndicator style={styles.imageLoadingIndicatorStyle} />
|
|
495
501
|
</View>
|
|
496
502
|
)}
|
|
@@ -40,6 +40,7 @@ export type VideoThumbnailProps = {
|
|
|
40
40
|
export const VideoThumbnail: React.FC<VideoThumbnailProps> = (props) => {
|
|
41
41
|
const {
|
|
42
42
|
theme: {
|
|
43
|
+
colors: { static_black, static_white },
|
|
43
44
|
messageSimple: {
|
|
44
45
|
videoThumbnail: { container, roundedView },
|
|
45
46
|
},
|
|
@@ -53,8 +54,8 @@ export const VideoThumbnail: React.FC<VideoThumbnailProps> = (props) => {
|
|
|
53
54
|
source={{ uri: thumb_url }}
|
|
54
55
|
style={[styles.container, container, style]}
|
|
55
56
|
>
|
|
56
|
-
<View style={[styles.roundedView, roundedView]}>
|
|
57
|
-
<Play height={24} pathFill={
|
|
57
|
+
<View style={[styles.roundedView, roundedView, { backgroundColor: static_white }]}>
|
|
58
|
+
<Play height={24} pathFill={static_black} width={24} />
|
|
58
59
|
</View>
|
|
59
60
|
</ImageBackground>
|
|
60
61
|
);
|
|
@@ -76,6 +76,7 @@ import type { DefaultStreamChatGenerics } from '../../types/types';
|
|
|
76
76
|
import { generateRandomId, MessageStatusTypes, ReactionData } from '../../utils/utils';
|
|
77
77
|
import { Attachment as AttachmentDefault } from '../Attachment/Attachment';
|
|
78
78
|
import { AttachmentActions as AttachmentActionsDefault } from '../Attachment/AttachmentActions';
|
|
79
|
+
import { AudioAttachment as AudioAttachmentDefault } from '../Attachment/AudioAttachment';
|
|
79
80
|
import { Card as CardDefault } from '../Attachment/Card';
|
|
80
81
|
import { FileAttachment as FileAttachmentDefault } from '../Attachment/FileAttachment';
|
|
81
82
|
import { FileAttachmentGroup as FileAttachmentGroupDefault } from '../Attachment/FileAttachmentGroup';
|
|
@@ -107,7 +108,6 @@ import { MessageSimple as MessageSimpleDefault } from '../Message/MessageSimple/
|
|
|
107
108
|
import { MessageStatus as MessageStatusDefault } from '../Message/MessageSimple/MessageStatus';
|
|
108
109
|
import { ReactionList as ReactionListDefault } from '../Message/MessageSimple/ReactionList';
|
|
109
110
|
import { AttachButton as AttachButtonDefault } from '../MessageInput/AttachButton';
|
|
110
|
-
import { AudioAttachmentUploadPreview as AudioAttachmentUploadPreviewDefault } from '../MessageInput/AudioAttachmentUploadPreview';
|
|
111
111
|
import { CommandsButton as CommandsButtonDefault } from '../MessageInput/CommandsButton';
|
|
112
112
|
import { InputEditingStateHeader as InputEditingStateHeaderDefault } from '../MessageInput/components/InputEditingStateHeader';
|
|
113
113
|
import { InputGiphySearch as InputGiphyCommandInputDefault } from '../MessageInput/components/InputGiphySearch';
|
|
@@ -399,7 +399,7 @@ const ChannelWithContext = <
|
|
|
399
399
|
AttachButton = AttachButtonDefault,
|
|
400
400
|
Attachment = AttachmentDefault,
|
|
401
401
|
AttachmentActions = AttachmentActionsDefault,
|
|
402
|
-
|
|
402
|
+
AudioAttachment = AudioAttachmentDefault,
|
|
403
403
|
AutoCompleteSuggestionHeader = AutoCompleteSuggestionHeaderDefault,
|
|
404
404
|
AutoCompleteSuggestionItem = AutoCompleteSuggestionItemDefault,
|
|
405
405
|
AutoCompleteSuggestionList = AutoCompleteSuggestionListDefault,
|
|
@@ -1620,7 +1620,7 @@ const ChannelWithContext = <
|
|
|
1620
1620
|
const inputMessageInputContext = useCreateInputMessageInputContext<StreamChatGenerics>({
|
|
1621
1621
|
additionalTextInputProps,
|
|
1622
1622
|
AttachButton,
|
|
1623
|
-
|
|
1623
|
+
AudioAttachment,
|
|
1624
1624
|
autoCompleteSuggestionsLimit,
|
|
1625
1625
|
autoCompleteTriggerSettings,
|
|
1626
1626
|
channelId,
|
|
@@ -8,7 +8,7 @@ export const useCreateInputMessageInputContext = <
|
|
|
8
8
|
>({
|
|
9
9
|
additionalTextInputProps,
|
|
10
10
|
AttachButton,
|
|
11
|
-
|
|
11
|
+
AudioAttachment,
|
|
12
12
|
autoCompleteSuggestionsLimit,
|
|
13
13
|
autoCompleteTriggerSettings,
|
|
14
14
|
channelId,
|
|
@@ -65,7 +65,7 @@ export const useCreateInputMessageInputContext = <
|
|
|
65
65
|
() => ({
|
|
66
66
|
additionalTextInputProps,
|
|
67
67
|
AttachButton,
|
|
68
|
-
|
|
68
|
+
AudioAttachment,
|
|
69
69
|
autoCompleteSuggestionsLimit,
|
|
70
70
|
autoCompleteTriggerSettings,
|
|
71
71
|
clearEditingState,
|
|
@@ -53,7 +53,7 @@ export const ImageGalleryVideoControl: React.FC<ImageGalleryFooterVideoControlPr
|
|
|
53
53
|
|
|
54
54
|
const {
|
|
55
55
|
theme: {
|
|
56
|
-
colors: {
|
|
56
|
+
colors: { static_black, static_white },
|
|
57
57
|
imageGallery: {
|
|
58
58
|
videoControl: { durationTextStyle, roundedView, videoContainer },
|
|
59
59
|
},
|
|
@@ -68,23 +68,28 @@ export const ImageGalleryVideoControl: React.FC<ImageGalleryFooterVideoControlPr
|
|
|
68
68
|
onPlayPause();
|
|
69
69
|
}}
|
|
70
70
|
>
|
|
71
|
-
<View style={[styles.roundedView, roundedView, { backgroundColor:
|
|
71
|
+
<View style={[styles.roundedView, roundedView, { backgroundColor: static_white }]}>
|
|
72
72
|
{paused ? (
|
|
73
|
-
<Play accessibilityLabel='Play Icon' height={24} pathFill={
|
|
73
|
+
<Play accessibilityLabel='Play Icon' height={24} pathFill={static_black} width={24} />
|
|
74
74
|
) : (
|
|
75
|
-
<Pause
|
|
75
|
+
<Pause
|
|
76
|
+
accessibilityLabel='Pause Icon'
|
|
77
|
+
height={24}
|
|
78
|
+
pathFill={static_black}
|
|
79
|
+
width={24}
|
|
80
|
+
/>
|
|
76
81
|
)}
|
|
77
82
|
</View>
|
|
78
83
|
</TouchableOpacity>
|
|
79
84
|
<Text
|
|
80
85
|
accessibilityLabel='Progress Duration'
|
|
81
|
-
style={[styles.durationTextStyle, durationTextStyle, { color:
|
|
86
|
+
style={[styles.durationTextStyle, durationTextStyle, { color: static_white }]}
|
|
82
87
|
>
|
|
83
88
|
{progressDuration ? progressDuration : '00:00'}
|
|
84
89
|
</Text>
|
|
85
90
|
<ProgressControl
|
|
86
91
|
duration={duration}
|
|
87
|
-
filledColor={
|
|
92
|
+
filledColor={static_white}
|
|
88
93
|
onPlayPause={onPlayPause}
|
|
89
94
|
onProgressDrag={onProgressDrag}
|
|
90
95
|
progress={progress}
|
|
@@ -93,7 +98,7 @@ export const ImageGalleryVideoControl: React.FC<ImageGalleryFooterVideoControlPr
|
|
|
93
98
|
/>
|
|
94
99
|
<Text
|
|
95
100
|
accessibilityLabel='Video Duration'
|
|
96
|
-
style={[styles.durationTextStyle, durationTextStyle, { color:
|
|
101
|
+
style={[styles.durationTextStyle, durationTextStyle, { color: static_white }]}
|
|
97
102
|
>
|
|
98
103
|
{videoDuration ? videoDuration : '00:00'}
|
|
99
104
|
</Text>
|
|
@@ -196,13 +196,15 @@ describe('MessageContent', () => {
|
|
|
196
196
|
user,
|
|
197
197
|
});
|
|
198
198
|
|
|
199
|
-
const { getByTestId, queryAllByTestId } = renderMessage({ message });
|
|
199
|
+
const { getByTestId, queryAllByA11yLabel, queryAllByTestId } = renderMessage({ message });
|
|
200
200
|
|
|
201
201
|
const fileAttachments = queryAllByTestId('file-attachment');
|
|
202
|
+
const audioAttachments = queryAllByA11yLabel('audio-attachment-preview');
|
|
202
203
|
|
|
203
204
|
await waitFor(() => {
|
|
204
205
|
expect(getByTestId('message-content-wrapper')).toBeTruthy();
|
|
205
|
-
expect(fileAttachments).toHaveLength(
|
|
206
|
+
expect(fileAttachments).toHaveLength(1);
|
|
207
|
+
expect(audioAttachments).toHaveLength(1);
|
|
206
208
|
});
|
|
207
209
|
});
|
|
208
210
|
|
|
@@ -22,6 +22,10 @@ describe('parseLinksFromText', () => {
|
|
|
22
22
|
],
|
|
23
23
|
['127.0.0.1/local_(development)_server', '127.0.0.1/local_(development)_server'],
|
|
24
24
|
['https://a.co:8999/ab.php?p=12', 'a.co:8999/ab.php?p=12'],
|
|
25
|
+
[
|
|
26
|
+
'http://help.apple.com/xcode/mac/current/#/devba7f53ad4',
|
|
27
|
+
'help.apple.com/xcode/mac/current/#/devba7f53ad4',
|
|
28
|
+
],
|
|
25
29
|
])('Returns the encoded value of %p as %p', (link, expected) => {
|
|
26
30
|
const result = parseLinksFromText(link);
|
|
27
31
|
|
|
@@ -11,7 +11,7 @@ const schema = `(\\w{2,15}:\\/\\/)`;
|
|
|
11
11
|
// something.tld OR 123.123.123.123
|
|
12
12
|
const domain = `((?:\\w+\\.[a-zA-Z]+)+(?:[^:\\/\\s]+)|(?:\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}))`;
|
|
13
13
|
const port = `(:[0-9]{1,5})`;
|
|
14
|
-
const path = `((?:\\/)?[
|
|
14
|
+
const path = `((?:\\/)?[^?\\s]+)`;
|
|
15
15
|
const queryString = `(\\?[^#\\s]+)`;
|
|
16
16
|
const fragment = `(#[\\w_-]+)`;
|
|
17
17
|
|
|
@@ -123,7 +123,7 @@ type FileUploadPreviewPropsWithContext<
|
|
|
123
123
|
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
|
|
124
124
|
> = Pick<
|
|
125
125
|
MessageInputContextValue<StreamChatGenerics>,
|
|
126
|
-
'fileUploads' | 'removeFile' | 'uploadFile' | 'setFileUploads' | '
|
|
126
|
+
'fileUploads' | 'removeFile' | 'uploadFile' | 'setFileUploads' | 'AudioAttachment'
|
|
127
127
|
> &
|
|
128
128
|
Pick<MessagesContextValue<StreamChatGenerics>, 'FileAttachmentIcon'>;
|
|
129
129
|
|
|
@@ -133,7 +133,7 @@ const FileUploadPreviewWithContext = <
|
|
|
133
133
|
props: FileUploadPreviewPropsWithContext<StreamChatGenerics>,
|
|
134
134
|
) => {
|
|
135
135
|
const {
|
|
136
|
-
|
|
136
|
+
AudioAttachment,
|
|
137
137
|
FileAttachmentIcon,
|
|
138
138
|
fileUploads,
|
|
139
139
|
removeFile,
|
|
@@ -172,8 +172,8 @@ const FileUploadPreviewWithContext = <
|
|
|
172
172
|
};
|
|
173
173
|
|
|
174
174
|
// The handler which controls or sets the paused/played state of the audio.
|
|
175
|
-
const onPlayPause = (index: string,
|
|
176
|
-
if (
|
|
175
|
+
const onPlayPause = (index: string, pausedStatus?: boolean) => {
|
|
176
|
+
if (pausedStatus === false) {
|
|
177
177
|
// If the status is false we set the audio with the index as playing and the others as paused.
|
|
178
178
|
setFileUploads((prevFileUploads) =>
|
|
179
179
|
prevFileUploads.map((fileUpload) => ({
|
|
@@ -230,7 +230,7 @@ const FileUploadPreviewWithContext = <
|
|
|
230
230
|
audioAttachmentFileContainer,
|
|
231
231
|
]}
|
|
232
232
|
>
|
|
233
|
-
<
|
|
233
|
+
<AudioAttachment
|
|
234
234
|
index={index}
|
|
235
235
|
item={item}
|
|
236
236
|
onLoad={onLoad}
|
|
@@ -296,18 +296,9 @@ const FileUploadPreviewWithContext = <
|
|
|
296
296
|
style={[styles.dismiss, { backgroundColor: grey_gainsboro }, dismiss]}
|
|
297
297
|
testID='remove-file-upload-preview'
|
|
298
298
|
>
|
|
299
|
-
<Close />
|
|
299
|
+
<Close pathFill={grey_dark} />
|
|
300
300
|
</TouchableOpacity>
|
|
301
301
|
</UploadProgressIndicator>
|
|
302
|
-
<TouchableOpacity
|
|
303
|
-
onPress={() => {
|
|
304
|
-
removeFile(item.id);
|
|
305
|
-
}}
|
|
306
|
-
style={[styles.dismiss, { backgroundColor: grey_gainsboro }, dismiss]}
|
|
307
|
-
testID='remove-file-upload-preview'
|
|
308
|
-
>
|
|
309
|
-
<Close pathFill={grey_dark} />
|
|
310
|
-
</TouchableOpacity>
|
|
311
302
|
</>
|
|
312
303
|
);
|
|
313
304
|
};
|
|
@@ -380,14 +371,14 @@ export const FileUploadPreview = <
|
|
|
380
371
|
>(
|
|
381
372
|
props: FileUploadPreviewProps<StreamChatGenerics>,
|
|
382
373
|
) => {
|
|
383
|
-
const {
|
|
374
|
+
const { AudioAttachment, fileUploads, removeFile, setFileUploads, uploadFile } =
|
|
384
375
|
useMessageInputContext<StreamChatGenerics>();
|
|
385
376
|
const { FileAttachmentIcon } = useMessagesContext<StreamChatGenerics>();
|
|
386
377
|
|
|
387
378
|
return (
|
|
388
379
|
<MemoizedFileUploadPreview
|
|
389
380
|
{...{
|
|
390
|
-
|
|
381
|
+
AudioAttachment,
|
|
391
382
|
FileAttachmentIcon,
|
|
392
383
|
fileUploads,
|
|
393
384
|
removeFile,
|
|
@@ -9,10 +9,7 @@ import { ThemeProvider } from '../../../contexts/themeContext/ThemeContext';
|
|
|
9
9
|
import { defaultTheme } from '../../../contexts/themeContext/utils/theme';
|
|
10
10
|
|
|
11
11
|
import { generateFileUploadPreview } from '../../../mock-builders/generator/attachment';
|
|
12
|
-
import {
|
|
13
|
-
AudioAttachmentUploadPreview,
|
|
14
|
-
AudioAttachmentUploadPreviewProps,
|
|
15
|
-
} from '../AudioAttachmentUploadPreview';
|
|
12
|
+
import { AudioAttachment, AudioAttachmentProps } from '../../Attachment/AudioAttachment';
|
|
16
13
|
|
|
17
14
|
jest.mock('../../../native.ts', () => ({
|
|
18
15
|
isAudioPackageAvailable: jest.fn(() => true),
|
|
@@ -29,13 +26,13 @@ jest.mock('react-native/Libraries/ReactNative/I18nManager', () => ({
|
|
|
29
26
|
isRTL: true,
|
|
30
27
|
}));
|
|
31
28
|
|
|
32
|
-
const getComponent = (props: Partial<
|
|
29
|
+
const getComponent = (props: Partial<AudioAttachmentProps>) => (
|
|
33
30
|
<ThemeProvider theme={defaultTheme}>
|
|
34
|
-
<
|
|
31
|
+
<AudioAttachment {...(props as unknown as AudioAttachmentProps)} />,
|
|
35
32
|
</ThemeProvider>
|
|
36
33
|
);
|
|
37
34
|
|
|
38
|
-
describe('
|
|
35
|
+
describe('AudioAttachmentExpo', () => {
|
|
39
36
|
it('handle play pause button when isPausedStatusAvailable unavailable and progress 1', () => {
|
|
40
37
|
const setPositionAsyncMock = jest.fn();
|
|
41
38
|
jest.spyOn(React, 'useRef').mockReturnValue({
|
|
@@ -9,10 +9,7 @@ import { ThemeProvider } from '../../../contexts/themeContext/ThemeContext';
|
|
|
9
9
|
import { defaultTheme } from '../../../contexts/themeContext/utils/theme';
|
|
10
10
|
|
|
11
11
|
import { generateFileUploadPreview } from '../../../mock-builders/generator/attachment';
|
|
12
|
-
import {
|
|
13
|
-
AudioAttachmentUploadPreview,
|
|
14
|
-
AudioAttachmentUploadPreviewProps,
|
|
15
|
-
} from '../AudioAttachmentUploadPreview';
|
|
12
|
+
import { AudioAttachment, AudioAttachmentProps } from '../../Attachment/AudioAttachment';
|
|
16
13
|
|
|
17
14
|
jest.mock('../../../native.ts', () => {
|
|
18
15
|
const View = require('react-native/Libraries/Components/View/View');
|
|
@@ -28,13 +25,13 @@ jest.mock('../../../native.ts', () => {
|
|
|
28
25
|
};
|
|
29
26
|
});
|
|
30
27
|
|
|
31
|
-
const getComponent = (props: Partial<
|
|
28
|
+
const getComponent = (props: Partial<AudioAttachmentProps>) => (
|
|
32
29
|
<ThemeProvider theme={defaultTheme}>
|
|
33
|
-
<
|
|
30
|
+
<AudioAttachment {...(props as unknown as AudioAttachmentProps)} />,
|
|
34
31
|
</ThemeProvider>
|
|
35
32
|
);
|
|
36
33
|
|
|
37
|
-
describe('
|
|
34
|
+
describe('AudioAttachment', () => {
|
|
38
35
|
it('handle play pause button when isPausedStatusAvailable unavailable and progress 1', () => {
|
|
39
36
|
const seekMock = jest.fn();
|
|
40
37
|
jest.spyOn(React, 'useRef').mockReturnValue({
|
|
@@ -351,13 +351,13 @@ describe('FileUploadPreview', () => {
|
|
|
351
351
|
</OverlayProvider>,
|
|
352
352
|
);
|
|
353
353
|
|
|
354
|
-
const
|
|
354
|
+
const AudioAttachmentComponent = getByTestId('audio-attachment-upload-preview');
|
|
355
355
|
|
|
356
356
|
await waitFor(() => {
|
|
357
|
-
fireEvent(
|
|
358
|
-
fireEvent(
|
|
359
|
-
fireEvent(
|
|
360
|
-
fireEvent(
|
|
357
|
+
fireEvent(AudioAttachmentComponent, 'onLoad');
|
|
358
|
+
fireEvent(AudioAttachmentComponent, 'onProgress');
|
|
359
|
+
fireEvent(AudioAttachmentComponent, 'onPlayPause');
|
|
360
|
+
fireEvent(AudioAttachmentComponent, 'onPlayPause', {
|
|
361
361
|
status: false,
|
|
362
362
|
});
|
|
363
363
|
});
|
package/src/components/index.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export * from './Attachment/Attachment';
|
|
2
2
|
export * from './Attachment/AttachmentActions';
|
|
3
|
+
export * from './Attachment/AudioAttachment';
|
|
3
4
|
export * from './Attachment/Card';
|
|
4
5
|
export * from './Attachment/FileAttachment';
|
|
5
6
|
export * from './Attachment/FileAttachmentGroup';
|
|
@@ -113,7 +114,6 @@ export * from './MessageInput/AttachButton';
|
|
|
113
114
|
export * from './MessageInput/CommandsButton';
|
|
114
115
|
export * from './MessageInput/CooldownTimer';
|
|
115
116
|
export * from './MessageInput/FileUploadPreview';
|
|
116
|
-
export * from './MessageInput/AudioAttachmentUploadPreview';
|
|
117
117
|
export * from './MessageInput/ImageUploadPreview';
|
|
118
118
|
export * from './MessageInput/InputButtons';
|
|
119
119
|
export * from './MessageInput/MessageInput';
|
|
@@ -21,8 +21,8 @@ import {
|
|
|
21
21
|
import { useCreateMessageInputContext } from './hooks/useCreateMessageInputContext';
|
|
22
22
|
import { isEditingBoolean, useMessageDetailsForState } from './hooks/useMessageDetailsForState';
|
|
23
23
|
|
|
24
|
+
import type { AudioAttachmentProps } from '../../components/Attachment/AudioAttachment';
|
|
24
25
|
import type { AttachButtonProps } from '../../components/MessageInput/AttachButton';
|
|
25
|
-
import type { AudioAttachmentUploadPreviewProps } from '../../components/MessageInput/AudioAttachmentUploadPreview';
|
|
26
26
|
import type { CommandsButtonProps } from '../../components/MessageInput/CommandsButton';
|
|
27
27
|
import type { InputEditingStateHeaderProps } from '../../components/MessageInput/components/InputEditingStateHeader';
|
|
28
28
|
import type { InputGiphySearchProps } from '../../components/MessageInput/components/InputGiphySearch';
|
|
@@ -225,10 +225,8 @@ export type InputMessageInputContextValue<
|
|
|
225
225
|
*/
|
|
226
226
|
AttachButton: React.ComponentType<AttachButtonProps<StreamChatGenerics>>;
|
|
227
227
|
|
|
228
|
-
/** Custom UI component for
|
|
229
|
-
|
|
230
|
-
AudioAttachmentUploadPreviewProps<StreamChatGenerics>
|
|
231
|
-
>;
|
|
228
|
+
/** Custom UI component for AudioAttachment. */
|
|
229
|
+
AudioAttachment: React.ComponentType<AudioAttachmentProps<StreamChatGenerics>>;
|
|
232
230
|
|
|
233
231
|
clearEditingState: () => void;
|
|
234
232
|
clearQuotedMessageState: () => void;
|
|
@@ -12,7 +12,7 @@ export const useCreateMessageInputContext = <
|
|
|
12
12
|
asyncIds,
|
|
13
13
|
asyncUploads,
|
|
14
14
|
AttachButton,
|
|
15
|
-
|
|
15
|
+
AudioAttachment,
|
|
16
16
|
autoCompleteSuggestionsLimit,
|
|
17
17
|
clearEditingState,
|
|
18
18
|
clearQuotedMessageState,
|
|
@@ -116,7 +116,7 @@ export const useCreateMessageInputContext = <
|
|
|
116
116
|
asyncIds,
|
|
117
117
|
asyncUploads,
|
|
118
118
|
AttachButton,
|
|
119
|
-
|
|
119
|
+
AudioAttachment,
|
|
120
120
|
autoCompleteSuggestionsLimit,
|
|
121
121
|
clearEditingState,
|
|
122
122
|
clearQuotedMessageState,
|
|
@@ -247,12 +247,12 @@ export type Theme = {
|
|
|
247
247
|
editingBoxHeaderTitle: TextStyle;
|
|
248
248
|
};
|
|
249
249
|
fileUploadPreview: {
|
|
250
|
-
|
|
251
|
-
audioAttachmentUploadPreview: {
|
|
250
|
+
audioAttachment: {
|
|
252
251
|
progressControlView: ViewStyle;
|
|
253
252
|
progressDurationText: TextStyle;
|
|
254
253
|
roundedView: ViewStyle;
|
|
255
254
|
};
|
|
255
|
+
audioAttachmentFileContainer: ViewStyle;
|
|
256
256
|
dismiss: ViewStyle;
|
|
257
257
|
fileContainer: ViewStyle;
|
|
258
258
|
fileContentContainer: ViewStyle;
|
|
@@ -746,12 +746,12 @@ export const defaultTheme: Theme = {
|
|
|
746
746
|
editingBoxHeaderTitle: {},
|
|
747
747
|
},
|
|
748
748
|
fileUploadPreview: {
|
|
749
|
-
|
|
750
|
-
audioAttachmentUploadPreview: {
|
|
749
|
+
audioAttachment: {
|
|
751
750
|
progressControlView: {},
|
|
752
751
|
progressDurationText: {},
|
|
753
752
|
roundedView: {},
|
|
754
753
|
},
|
|
754
|
+
audioAttachmentFileContainer: {},
|
|
755
755
|
dismiss: {},
|
|
756
756
|
fileContainer: {},
|
|
757
757
|
fileContentContainer: {},
|
package/src/version.json
CHANGED