react-native-gifted-chat 2.8.1 → 2.8.2-alpha.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/README.md +18 -17
- package/package.json +41 -35
- package/src/Bubble/index.tsx +15 -39
- package/src/Bubble/types.ts +5 -5
- package/src/Composer.tsx +19 -26
- package/src/Constant.ts +0 -1
- package/src/GiftedAvatar.tsx +29 -36
- package/src/GiftedChat/index.tsx +34 -65
- package/src/GiftedChat/types.ts +8 -53
- package/src/InputToolbar.tsx +25 -8
- package/src/LoadEarlier.tsx +19 -17
- package/src/MessageAudio.tsx +19 -7
- package/src/MessageContainer/components/DayAnimated/index.tsx +14 -9
- package/src/MessageContainer/components/Item/index.tsx +7 -1
- package/src/MessageContainer/index.tsx +104 -64
- package/src/MessageContainer/styles.ts +3 -2
- package/src/MessageContainer/types.ts +36 -14
- package/src/MessageImage.tsx +18 -6
- package/src/MessageText.tsx +88 -128
- package/src/MessageVideo.tsx +19 -7
- package/src/QuickReplies.tsx +17 -10
- package/src/Send.tsx +7 -1
- package/src/SystemMessage.tsx +12 -2
- package/src/Time.tsx +9 -2
- package/src/TypingIndicator/index.tsx +2 -1
- package/src/TypingIndicator/types.ts +3 -0
- package/src/__tests__/Actions.test.tsx +3 -4
- package/src/__tests__/Avatar.test.tsx +5 -6
- package/src/__tests__/Bubble.test.tsx +14 -19
- package/src/__tests__/Composer.test.tsx +3 -4
- package/src/__tests__/Day.test.tsx +5 -8
- package/src/__tests__/DayAnimated.test.tsx +52 -0
- package/src/__tests__/GiftedAvatar.test.tsx +3 -8
- package/src/__tests__/GiftedChat.test.tsx +37 -21
- package/src/__tests__/InputToolbar.test.tsx +3 -4
- package/src/__tests__/LoadEarlier.test.tsx +3 -4
- package/src/__tests__/Message.test.tsx +51 -58
- package/src/__tests__/MessageContainer.test.tsx +39 -5
- package/src/__tests__/MessageImage.test.tsx +12 -15
- package/src/__tests__/MessageText.test.tsx +7 -4
- package/src/__tests__/Send.test.tsx +7 -8
- package/src/__tests__/SystemMessage.test.tsx +12 -15
- package/src/__tests__/Time.test.tsx +5 -8
- package/src/__tests__/__snapshots__/Bubble.test.tsx.snap +48 -50
- package/src/__tests__/__snapshots__/Composer.test.tsx.snap +1 -2
- package/src/__tests__/__snapshots__/Constant.test.tsx.snap +0 -1
- package/src/__tests__/__snapshots__/DayAnimated.test.tsx.snap +5 -0
- package/src/__tests__/__snapshots__/GiftedChat.test.tsx.snap +25 -0
- package/src/__tests__/__snapshots__/InputToolbar.test.tsx.snap +2 -2
- package/src/__tests__/__snapshots__/Message.test.tsx.snap +146 -150
- package/src/__tests__/__snapshots__/MessageImage.test.tsx.snap +12 -10
- package/src/__tests__/__snapshots__/MessageText.test.tsx.snap +12 -8
- package/src/__tests__/__snapshots__/Send.test.tsx.snap +2 -0
- package/src/reanimatedCompat.ts +27 -0
- package/src/types.ts +4 -0
- package/src/utils.ts +77 -1
- package/lib/Actions.d.ts +0 -14
- package/lib/Actions.js +0 -57
- package/lib/Actions.js.map +0 -1
- package/lib/Avatar.d.ts +0 -18
- package/lib/Avatar.js +0 -93
- package/lib/Avatar.js.map +0 -1
- package/lib/Bubble/index.d.ts +0 -6
- package/lib/Bubble/index.js +0 -257
- package/lib/Bubble/index.js.map +0 -1
- package/lib/Bubble/styles.d.ts +0 -69
- package/lib/Bubble/styles.js +0 -72
- package/lib/Bubble/styles.js.map +0 -1
- package/lib/Bubble/types.d.ts +0 -47
- package/lib/Bubble/types.js +0 -2
- package/lib/Bubble/types.js.map +0 -1
- package/lib/Color.d.ts +0 -18
- package/lib/Color.js +0 -18
- package/lib/Color.js.map +0 -1
- package/lib/Composer.d.ts +0 -20
- package/lib/Composer.js +0 -60
- package/lib/Composer.js.map +0 -1
- package/lib/Constant.d.ts +0 -10
- package/lib/Constant.js +0 -17
- package/lib/Constant.js.map +0 -1
- package/lib/Day/index.d.ts +0 -4
- package/lib/Day/index.js +0 -39
- package/lib/Day/index.js.map +0 -1
- package/lib/Day/styles.d.ts +0 -20
- package/lib/Day/styles.js +0 -22
- package/lib/Day/styles.js.map +0 -1
- package/lib/Day/types.d.ts +0 -9
- package/lib/Day/types.js +0 -2
- package/lib/Day/types.js.map +0 -1
- package/lib/GiftedAvatar.d.ts +0 -11
- package/lib/GiftedAvatar.js +0 -104
- package/lib/GiftedAvatar.js.map +0 -1
- package/lib/GiftedChat/index.d.ts +0 -26
- package/lib/GiftedChat/index.js +0 -302
- package/lib/GiftedChat/index.js.map +0 -1
- package/lib/GiftedChat/styles.d.ts +0 -6
- package/lib/GiftedChat/styles.js +0 -7
- package/lib/GiftedChat/styles.js.map +0 -1
- package/lib/GiftedChat/types.d.ts +0 -117
- package/lib/GiftedChat/types.js +0 -2
- package/lib/GiftedChat/types.js.map +0 -1
- package/lib/GiftedChatContext.d.ts +0 -9
- package/lib/GiftedChatContext.js +0 -9
- package/lib/GiftedChatContext.js.map +0 -1
- package/lib/InputToolbar.d.ts +0 -23
- package/lib/InputToolbar.js +0 -56
- package/lib/InputToolbar.js.map +0 -1
- package/lib/LoadEarlier.d.ts +0 -14
- package/lib/LoadEarlier.js +0 -45
- package/lib/LoadEarlier.js.map +0 -1
- package/lib/Message/index.d.ts +0 -6
- package/lib/Message/index.js +0 -80
- package/lib/Message/index.js.map +0 -1
- package/lib/Message/styles.d.ts +0 -21
- package/lib/Message/styles.js +0 -22
- package/lib/Message/styles.js.map +0 -1
- package/lib/Message/types.d.ts +0 -22
- package/lib/Message/types.js +0 -2
- package/lib/Message/types.js.map +0 -1
- package/lib/MessageAudio.d.ts +0 -2
- package/lib/MessageAudio.js +0 -14
- package/lib/MessageAudio.js.map +0 -1
- package/lib/MessageContainer/components/DayAnimated/index.d.ts +0 -5
- package/lib/MessageContainer/components/DayAnimated/index.js +0 -85
- package/lib/MessageContainer/components/DayAnimated/index.js.map +0 -1
- package/lib/MessageContainer/components/DayAnimated/styles.d.ts +0 -11
- package/lib/MessageContainer/components/DayAnimated/styles.js +0 -12
- package/lib/MessageContainer/components/DayAnimated/styles.js.map +0 -1
- package/lib/MessageContainer/components/DayAnimated/types.d.ts +0 -17
- package/lib/MessageContainer/components/DayAnimated/types.js +0 -2
- package/lib/MessageContainer/components/DayAnimated/types.js.map +0 -1
- package/lib/MessageContainer/components/Item/index.d.ts +0 -23
- package/lib/MessageContainer/components/Item/index.js +0 -88
- package/lib/MessageContainer/components/Item/index.js.map +0 -1
- package/lib/MessageContainer/components/Item/types.d.ts +0 -17
- package/lib/MessageContainer/components/Item/types.js +0 -2
- package/lib/MessageContainer/components/Item/types.js.map +0 -1
- package/lib/MessageContainer/index.d.ts +0 -6
- package/lib/MessageContainer/index.js +0 -224
- package/lib/MessageContainer/index.js.map +0 -1
- package/lib/MessageContainer/styles.d.ts +0 -34
- package/lib/MessageContainer/styles.js +0 -31
- package/lib/MessageContainer/styles.js.map +0 -1
- package/lib/MessageContainer/types.d.ts +0 -54
- package/lib/MessageContainer/types.js +0 -2
- package/lib/MessageContainer/types.js.map +0 -1
- package/lib/MessageImage.d.ts +0 -13
- package/lib/MessageImage.js +0 -30
- package/lib/MessageImage.js.map +0 -1
- package/lib/MessageText.d.ts +0 -15
- package/lib/MessageText.js +0 -108
- package/lib/MessageText.js.map +0 -1
- package/lib/MessageVideo.d.ts +0 -2
- package/lib/MessageVideo.js +0 -14
- package/lib/MessageVideo.js.map +0 -1
- package/lib/QuickReplies.d.ts +0 -15
- package/lib/QuickReplies.js +0 -101
- package/lib/QuickReplies.js.map +0 -1
- package/lib/Send.d.ts +0 -15
- package/lib/Send.js +0 -34
- package/lib/Send.js.map +0 -1
- package/lib/SystemMessage.d.ts +0 -10
- package/lib/SystemMessage.js +0 -26
- package/lib/SystemMessage.js.map +0 -1
- package/lib/Time.d.ts +0 -11
- package/lib/Time.js +0 -56
- package/lib/Time.js.map +0 -1
- package/lib/TypingIndicator/index.d.ts +0 -5
- package/lib/TypingIndicator/index.js +0 -94
- package/lib/TypingIndicator/index.js.map +0 -1
- package/lib/TypingIndicator/styles.d.ts +0 -20
- package/lib/TypingIndicator/styles.js +0 -22
- package/lib/TypingIndicator/styles.js.map +0 -1
- package/lib/TypingIndicator/types.d.ts +0 -3
- package/lib/TypingIndicator/types.js +0 -2
- package/lib/TypingIndicator/types.js.map +0 -1
- package/lib/hooks/useUpdateLayoutEffect.d.ts +0 -8
- package/lib/hooks/useUpdateLayoutEffect.js +0 -17
- package/lib/hooks/useUpdateLayoutEffect.js.map +0 -1
- package/lib/index.d.ts +0 -4
- package/lib/index.js +0 -5
- package/lib/index.js.map +0 -1
- package/lib/logging.d.ts +0 -2
- package/lib/logging.js +0 -5
- package/lib/logging.js.map +0 -1
- package/lib/styles.d.ts +0 -10
- package/lib/styles.js +0 -11
- package/lib/styles.js.map +0 -1
- package/lib/types.d.ts +0 -67
- package/lib/types.js +0 -2
- package/lib/types.js.map +0 -1
- package/lib/utils.d.ts +0 -3
- package/lib/utils.js +0 -17
- package/lib/utils.js.map +0 -1
- package/src/__tests__/__snapshots__/MessageContainer.test.tsx.snap +0 -101
package/src/MessageText.tsx
CHANGED
|
@@ -1,164 +1,124 @@
|
|
|
1
|
-
import React from 'react'
|
|
1
|
+
import React, { useMemo, useCallback } from 'react'
|
|
2
2
|
import {
|
|
3
3
|
Linking,
|
|
4
4
|
StyleSheet,
|
|
5
|
-
View,
|
|
6
|
-
TextProps,
|
|
7
5
|
StyleProp,
|
|
8
6
|
ViewStyle,
|
|
9
7
|
TextStyle,
|
|
8
|
+
View,
|
|
10
9
|
} from 'react-native'
|
|
11
10
|
|
|
12
|
-
import
|
|
11
|
+
import Autolink, { AutolinkProps } from 'react-native-autolink'
|
|
12
|
+
import { Match } from 'autolinker/dist/es2015'
|
|
13
13
|
import { LeftRightStyle, IMessage } from './types'
|
|
14
|
-
import { useChatContext } from './GiftedChatContext'
|
|
15
14
|
import { error } from './logging'
|
|
16
15
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
textStyle: {
|
|
21
|
-
fontSize: 16,
|
|
22
|
-
lineHeight: 20,
|
|
23
|
-
marginTop: 5,
|
|
24
|
-
marginBottom: 5,
|
|
25
|
-
marginLeft: 10,
|
|
26
|
-
marginRight: 10,
|
|
27
|
-
},
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
const styles = {
|
|
31
|
-
left: StyleSheet.create({
|
|
32
|
-
container: {},
|
|
33
|
-
text: {
|
|
34
|
-
color: 'black',
|
|
35
|
-
...textStyle,
|
|
36
|
-
},
|
|
37
|
-
link: {
|
|
38
|
-
color: 'black',
|
|
39
|
-
textDecorationLine: 'underline',
|
|
40
|
-
},
|
|
41
|
-
}),
|
|
42
|
-
right: StyleSheet.create({
|
|
43
|
-
container: {},
|
|
44
|
-
text: {
|
|
45
|
-
color: 'white',
|
|
46
|
-
...textStyle,
|
|
47
|
-
},
|
|
48
|
-
link: {
|
|
49
|
-
color: 'white',
|
|
50
|
-
textDecorationLine: 'underline',
|
|
51
|
-
},
|
|
52
|
-
}),
|
|
16
|
+
export interface MessageOption {
|
|
17
|
+
title: string
|
|
18
|
+
action: (phone: string) => void
|
|
53
19
|
}
|
|
54
20
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
export interface MessageTextProps<TMessage extends IMessage> {
|
|
21
|
+
export type MessageTextProps<TMessage extends IMessage> = {
|
|
58
22
|
position?: 'left' | 'right'
|
|
59
|
-
optionTitles?: string[]
|
|
60
23
|
currentMessage: TMessage
|
|
61
24
|
containerStyle?: LeftRightStyle<ViewStyle>
|
|
62
25
|
textStyle?: LeftRightStyle<TextStyle>
|
|
63
26
|
linkStyle?: LeftRightStyle<TextStyle>
|
|
64
|
-
textProps?: TextProps
|
|
65
27
|
customTextStyle?: StyleProp<TextStyle>
|
|
66
|
-
|
|
67
|
-
|
|
28
|
+
onPress?: (
|
|
29
|
+
message: TMessage,
|
|
30
|
+
url: string,
|
|
31
|
+
match: Match
|
|
32
|
+
) => void
|
|
33
|
+
} & Omit<AutolinkProps, 'text' | 'onPress'>
|
|
68
34
|
|
|
69
|
-
export
|
|
70
|
-
currentMessage = {} as
|
|
71
|
-
optionTitles = DEFAULT_OPTION_TITLES,
|
|
35
|
+
export const MessageText: React.FC<MessageTextProps<IMessage>> = ({
|
|
36
|
+
currentMessage = {} as IMessage,
|
|
72
37
|
position = 'left',
|
|
73
38
|
containerStyle,
|
|
74
39
|
textStyle,
|
|
75
40
|
linkStyle: linkStyleProp,
|
|
76
41
|
customTextStyle,
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}
|
|
80
|
-
const
|
|
42
|
+
onPress: onPressProp,
|
|
43
|
+
...rest
|
|
44
|
+
}) => {
|
|
45
|
+
const onUrlPress = useCallback((url: string) => {
|
|
46
|
+
if (/^www\./i.test(url))
|
|
47
|
+
url = `https://${url}`
|
|
81
48
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
// !!nextProps.currentMessage &&
|
|
87
|
-
// currentMessage.text !== nextProps.currentMessage.text
|
|
88
|
-
// )
|
|
89
|
-
// }
|
|
49
|
+
Linking.openURL(url).catch(e => {
|
|
50
|
+
error(e, 'No handler for URL:', url)
|
|
51
|
+
})
|
|
52
|
+
}, [])
|
|
90
53
|
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
else
|
|
97
|
-
Linking.openURL(url).catch(e => {
|
|
98
|
-
error(e, 'No handler for URL:', url)
|
|
99
|
-
})
|
|
100
|
-
}
|
|
54
|
+
const onPhonePress = useCallback((phone: string) => {
|
|
55
|
+
Linking.openURL(`tel:${phone}`).catch(e => {
|
|
56
|
+
error(e, 'No handler for telephone')
|
|
57
|
+
})
|
|
58
|
+
}, [])
|
|
101
59
|
|
|
102
|
-
const
|
|
103
|
-
const options =
|
|
104
|
-
optionTitles && optionTitles.length > 0
|
|
105
|
-
? optionTitles.slice(0, 3)
|
|
106
|
-
: DEFAULT_OPTION_TITLES
|
|
107
|
-
const cancelButtonIndex = options.length - 1
|
|
108
|
-
actionSheet().showActionSheetWithOptions(
|
|
109
|
-
{
|
|
110
|
-
options,
|
|
111
|
-
cancelButtonIndex,
|
|
112
|
-
},
|
|
113
|
-
(buttonIndex?: number) => {
|
|
114
|
-
switch (buttonIndex) {
|
|
115
|
-
case 0:
|
|
116
|
-
Linking.openURL(`tel:${phone}`).catch(e => {
|
|
117
|
-
error(e, 'No handler for telephone')
|
|
118
|
-
})
|
|
119
|
-
break
|
|
120
|
-
case 1:
|
|
121
|
-
Linking.openURL(`sms:${phone}`).catch(e => {
|
|
122
|
-
error(e, 'No handler for text')
|
|
123
|
-
})
|
|
124
|
-
break
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
)
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
const onEmailPress = (email: string) =>
|
|
60
|
+
const onEmailPress = useCallback((email: string) =>
|
|
131
61
|
Linking.openURL(`mailto:${email}`).catch(e =>
|
|
132
62
|
error(e, 'No handler for mailto')
|
|
133
|
-
)
|
|
63
|
+
), [])
|
|
134
64
|
|
|
135
|
-
const linkStyle = [
|
|
136
|
-
styles
|
|
65
|
+
const linkStyle = useMemo(() => StyleSheet.flatten([
|
|
66
|
+
styles.link,
|
|
137
67
|
linkStyleProp?.[position],
|
|
138
|
-
]
|
|
68
|
+
]), [position, linkStyleProp])
|
|
69
|
+
|
|
70
|
+
const handlePress = useCallback((url: string, match: Match) => {
|
|
71
|
+
const type = match.getType()
|
|
72
|
+
|
|
73
|
+
if (onPressProp)
|
|
74
|
+
onPressProp(currentMessage, url, match)
|
|
75
|
+
else if (type === 'url')
|
|
76
|
+
onUrlPress(url)
|
|
77
|
+
else if (type === 'phone')
|
|
78
|
+
onPhonePress(url)
|
|
79
|
+
else if (type === 'email')
|
|
80
|
+
onEmailPress(url)
|
|
81
|
+
}, [onUrlPress, onPhonePress, onEmailPress, onPressProp, currentMessage])
|
|
82
|
+
|
|
83
|
+
const style = useMemo(() => [
|
|
84
|
+
styles[`text_${position}`],
|
|
85
|
+
textStyle?.[position],
|
|
86
|
+
customTextStyle,
|
|
87
|
+
], [position, textStyle, customTextStyle])
|
|
88
|
+
|
|
139
89
|
return (
|
|
140
|
-
<View
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
customTextStyle,
|
|
151
|
-
]}
|
|
152
|
-
parse={[
|
|
153
|
-
...(parsePatterns ? parsePatterns(linkStyle as unknown as TextStyle) : []),
|
|
154
|
-
{ type: 'url', style: linkStyle, onPress: onUrlPress },
|
|
155
|
-
{ type: 'phone', style: linkStyle, onPress: onPhonePress },
|
|
156
|
-
{ type: 'email', style: linkStyle, onPress: onEmailPress },
|
|
157
|
-
]}
|
|
158
|
-
childrenProps={{ ...textProps }}
|
|
159
|
-
>
|
|
160
|
-
{currentMessage!.text}
|
|
161
|
-
</ParsedText>
|
|
90
|
+
<View style={[styles.container, containerStyle?.[position]]}>
|
|
91
|
+
<Autolink
|
|
92
|
+
style={style}
|
|
93
|
+
{...rest}
|
|
94
|
+
text={currentMessage!.text}
|
|
95
|
+
email
|
|
96
|
+
link
|
|
97
|
+
linkStyle={linkStyle}
|
|
98
|
+
onPress={handlePress}
|
|
99
|
+
/>
|
|
162
100
|
</View>
|
|
163
101
|
)
|
|
164
102
|
}
|
|
103
|
+
|
|
104
|
+
const styles = StyleSheet.create({
|
|
105
|
+
container: {
|
|
106
|
+
marginTop: 5,
|
|
107
|
+
marginBottom: 5,
|
|
108
|
+
marginLeft: 10,
|
|
109
|
+
marginRight: 10,
|
|
110
|
+
},
|
|
111
|
+
text: {
|
|
112
|
+
fontSize: 16,
|
|
113
|
+
lineHeight: 20,
|
|
114
|
+
},
|
|
115
|
+
text_left: {
|
|
116
|
+
color: 'black',
|
|
117
|
+
},
|
|
118
|
+
text_right: {
|
|
119
|
+
color: 'white',
|
|
120
|
+
},
|
|
121
|
+
link: {
|
|
122
|
+
textDecorationLine: 'underline',
|
|
123
|
+
},
|
|
124
|
+
})
|
package/src/MessageVideo.tsx
CHANGED
|
@@ -1,16 +1,28 @@
|
|
|
1
|
-
import React from 'react'
|
|
1
|
+
import React, { useMemo } from 'react'
|
|
2
2
|
import Color from './Color'
|
|
3
|
-
import { View, Text } from 'react-native'
|
|
3
|
+
import { View, Text, StyleSheet } from 'react-native'
|
|
4
|
+
|
|
5
|
+
const styles = StyleSheet.create({
|
|
6
|
+
container: {
|
|
7
|
+
padding: 20,
|
|
8
|
+
},
|
|
9
|
+
text: {
|
|
10
|
+
color: Color.alizarin,
|
|
11
|
+
fontWeight: '600',
|
|
12
|
+
},
|
|
13
|
+
})
|
|
4
14
|
|
|
5
15
|
export function MessageVideo () {
|
|
6
|
-
|
|
7
|
-
<View style={
|
|
8
|
-
<Text style={
|
|
16
|
+
const content = useMemo(() => (
|
|
17
|
+
<View style={styles.container}>
|
|
18
|
+
<Text style={styles.text}>
|
|
9
19
|
{'Video is not implemented by GiftedChat.'}
|
|
10
20
|
</Text>
|
|
11
|
-
<Text style={
|
|
21
|
+
<Text style={styles.text}>
|
|
12
22
|
{'\nYou need to provide your own implementation by using renderMessageVideo prop.'}
|
|
13
23
|
</Text>
|
|
14
24
|
</View>
|
|
15
|
-
)
|
|
25
|
+
), [])
|
|
26
|
+
|
|
27
|
+
return content
|
|
16
28
|
}
|
package/src/QuickReplies.tsx
CHANGED
|
@@ -122,6 +122,22 @@ export function QuickReplies ({
|
|
|
122
122
|
[replies, currentMessage, handleSend]
|
|
123
123
|
)
|
|
124
124
|
|
|
125
|
+
const renderSendButton = useMemo(() => {
|
|
126
|
+
if (!replies.length)
|
|
127
|
+
return null
|
|
128
|
+
|
|
129
|
+
return (
|
|
130
|
+
<TouchableOpacity
|
|
131
|
+
style={[stylesCommon.centerItems, styles.quickReply, styles.sendLink]}
|
|
132
|
+
onPress={handleSend(replies)}
|
|
133
|
+
>
|
|
134
|
+
{renderQuickReplySend?.() || (
|
|
135
|
+
<Text style={styles.sendLinkText}>{sendText}</Text>
|
|
136
|
+
)}
|
|
137
|
+
</TouchableOpacity>
|
|
138
|
+
)
|
|
139
|
+
}, [replies, handleSend, renderQuickReplySend, sendText])
|
|
140
|
+
|
|
125
141
|
if (!shouldComponentDisplay)
|
|
126
142
|
return null
|
|
127
143
|
|
|
@@ -159,16 +175,7 @@ export function QuickReplies ({
|
|
|
159
175
|
)
|
|
160
176
|
}
|
|
161
177
|
)}
|
|
162
|
-
{
|
|
163
|
-
<TouchableOpacity
|
|
164
|
-
style={[stylesCommon.centerItems, styles.quickReply, styles.sendLink]}
|
|
165
|
-
onPress={handleSend(replies)}
|
|
166
|
-
>
|
|
167
|
-
{renderQuickReplySend?.() || (
|
|
168
|
-
<Text style={styles.sendLinkText}>{sendText}</Text>
|
|
169
|
-
)}
|
|
170
|
-
</TouchableOpacity>
|
|
171
|
-
)}
|
|
178
|
+
{renderSendButton}
|
|
172
179
|
</View>
|
|
173
180
|
)
|
|
174
181
|
}
|
package/src/Send.tsx
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
ViewStyle,
|
|
9
9
|
TextStyle,
|
|
10
10
|
TouchableOpacityProps,
|
|
11
|
+
useColorScheme,
|
|
11
12
|
} from 'react-native'
|
|
12
13
|
|
|
13
14
|
import Color from './Color'
|
|
@@ -28,6 +29,9 @@ const styles = StyleSheet.create({
|
|
|
28
29
|
marginLeft: 10,
|
|
29
30
|
marginRight: 10,
|
|
30
31
|
},
|
|
32
|
+
text_dark: {
|
|
33
|
+
color: '#4da6ff',
|
|
34
|
+
},
|
|
31
35
|
})
|
|
32
36
|
|
|
33
37
|
export interface SendProps<TMessage extends IMessage> {
|
|
@@ -56,6 +60,8 @@ export const Send = <TMessage extends IMessage = IMessage>({
|
|
|
56
60
|
sendButtonProps,
|
|
57
61
|
onSend,
|
|
58
62
|
}: SendProps<TMessage>) => {
|
|
63
|
+
const colorScheme = useColorScheme()
|
|
64
|
+
|
|
59
65
|
const handleOnPress = useCallback(() => {
|
|
60
66
|
if (text && onSend)
|
|
61
67
|
onSend({ text: text.trim() } as Partial<TMessage>, true)
|
|
@@ -81,7 +87,7 @@ export const Send = <TMessage extends IMessage = IMessage>({
|
|
|
81
87
|
{...sendButtonProps}
|
|
82
88
|
>
|
|
83
89
|
<View>
|
|
84
|
-
{children || <Text style={[styles.text, textStyle]}>{label}</Text>}
|
|
90
|
+
{children || <Text style={[styles.text, styles[`text_${colorScheme}`], textStyle]}>{label}</Text>}
|
|
85
91
|
</View>
|
|
86
92
|
</TouchableOpacity>
|
|
87
93
|
)
|
package/src/SystemMessage.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React from 'react'
|
|
1
|
+
import React, { useMemo } from 'react'
|
|
2
2
|
import {
|
|
3
3
|
StyleSheet,
|
|
4
4
|
Text,
|
|
@@ -29,6 +29,7 @@ export interface SystemMessageProps<TMessage extends IMessage> {
|
|
|
29
29
|
containerStyle?: StyleProp<ViewStyle>
|
|
30
30
|
wrapperStyle?: StyleProp<ViewStyle>
|
|
31
31
|
textStyle?: StyleProp<TextStyle>
|
|
32
|
+
children?: React.ReactNode
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
export function SystemMessage<TMessage extends IMessage = IMessage> ({
|
|
@@ -36,14 +37,23 @@ export function SystemMessage<TMessage extends IMessage = IMessage> ({
|
|
|
36
37
|
containerStyle,
|
|
37
38
|
wrapperStyle,
|
|
38
39
|
textStyle,
|
|
40
|
+
children,
|
|
39
41
|
}: SystemMessageProps<TMessage>) {
|
|
42
|
+
const textContent = useMemo(() => {
|
|
43
|
+
if (!currentMessage?.text)
|
|
44
|
+
return null
|
|
45
|
+
|
|
46
|
+
return <Text style={[styles.text, textStyle]}>{currentMessage.text}</Text>
|
|
47
|
+
}, [currentMessage?.text, textStyle])
|
|
48
|
+
|
|
40
49
|
if (currentMessage == null || currentMessage.system === false)
|
|
41
50
|
return null
|
|
42
51
|
|
|
43
52
|
return (
|
|
44
53
|
<View style={[stylesCommon.fill, stylesCommon.centerItems, styles.container, containerStyle]}>
|
|
45
54
|
<View style={wrapperStyle}>
|
|
46
|
-
|
|
55
|
+
{textContent}
|
|
56
|
+
{children}
|
|
47
57
|
</View>
|
|
48
58
|
</View>
|
|
49
59
|
)
|
package/src/Time.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React from 'react'
|
|
1
|
+
import React, { useMemo } from 'react'
|
|
2
2
|
import { StyleSheet, Text, View, ViewStyle, TextStyle } from 'react-native'
|
|
3
3
|
import dayjs from 'dayjs'
|
|
4
4
|
|
|
@@ -60,6 +60,13 @@ export function Time<TMessage extends IMessage = IMessage> ({
|
|
|
60
60
|
}: TimeProps<TMessage>) {
|
|
61
61
|
const { getLocale } = useChatContext()
|
|
62
62
|
|
|
63
|
+
const formattedTime = useMemo(() => {
|
|
64
|
+
if (currentMessage == null)
|
|
65
|
+
return null
|
|
66
|
+
|
|
67
|
+
return dayjs(currentMessage.createdAt).locale(getLocale()).format(timeFormat)
|
|
68
|
+
}, [currentMessage, getLocale, timeFormat])
|
|
69
|
+
|
|
63
70
|
if (currentMessage == null)
|
|
64
71
|
return null
|
|
65
72
|
|
|
@@ -76,7 +83,7 @@ export function Time<TMessage extends IMessage = IMessage> ({
|
|
|
76
83
|
timeTextStyle?.[position],
|
|
77
84
|
]}
|
|
78
85
|
>
|
|
79
|
-
{
|
|
86
|
+
{formattedTime}
|
|
80
87
|
</Text>
|
|
81
88
|
</View>
|
|
82
89
|
)
|
|
@@ -89,7 +89,7 @@ const DotsAnimation = () => {
|
|
|
89
89
|
)
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
-
const TypingIndicator = ({ isTyping }: TypingIndicatorProps) => {
|
|
92
|
+
const TypingIndicator = ({ isTyping, style }: TypingIndicatorProps) => {
|
|
93
93
|
const yCoords = useSharedValue(200)
|
|
94
94
|
const heightScale = useSharedValue(0)
|
|
95
95
|
const marginScale = useSharedValue(0)
|
|
@@ -146,6 +146,7 @@ const TypingIndicator = ({ isTyping }: TypingIndicatorProps) => {
|
|
|
146
146
|
style={[
|
|
147
147
|
styles.container,
|
|
148
148
|
containerStyle,
|
|
149
|
+
style,
|
|
149
150
|
]}
|
|
150
151
|
>
|
|
151
152
|
<DotsAnimation />
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import 'react-native'
|
|
2
1
|
import React from 'react'
|
|
3
|
-
import
|
|
2
|
+
import { render } from '@testing-library/react-native'
|
|
4
3
|
|
|
5
4
|
import { Actions } from '../GiftedChat'
|
|
6
5
|
|
|
7
6
|
it('should render <Actions /> and compare with snapshot', () => {
|
|
8
|
-
const
|
|
9
|
-
expect(
|
|
7
|
+
const { toJSON } = render(<Actions />)
|
|
8
|
+
expect(toJSON()).toMatchSnapshot()
|
|
10
9
|
})
|
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
import 'react-native'
|
|
2
1
|
import React from 'react'
|
|
3
|
-
import
|
|
2
|
+
import { render } from '@testing-library/react-native'
|
|
4
3
|
|
|
5
4
|
import { Avatar } from '../GiftedChat'
|
|
6
5
|
|
|
7
6
|
it('should render <Avatar /> and compare with snapshot', () => {
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
const { toJSON } = render(
|
|
8
|
+
<Avatar renderAvatar={() => 'renderAvatar'} position='left' />
|
|
9
|
+
)
|
|
11
10
|
|
|
12
|
-
expect(
|
|
11
|
+
expect(toJSON()).toMatchSnapshot()
|
|
13
12
|
})
|
|
@@ -1,26 +1,21 @@
|
|
|
1
|
-
import 'react-native'
|
|
2
1
|
import React from 'react'
|
|
3
|
-
import
|
|
2
|
+
import { render } from '@testing-library/react-native'
|
|
4
3
|
|
|
5
4
|
import { Bubble } from '../GiftedChat'
|
|
6
5
|
|
|
7
6
|
it('should render <Bubble /> and compare with snapshot', () => {
|
|
8
|
-
|
|
7
|
+
const { toJSON } = render(
|
|
8
|
+
<Bubble
|
|
9
|
+
user={{ _id: 1 }}
|
|
10
|
+
currentMessage={{
|
|
11
|
+
_id: 1,
|
|
12
|
+
text: 'test',
|
|
13
|
+
createdAt: 1554744013721,
|
|
14
|
+
user: { _id: 1 },
|
|
15
|
+
}}
|
|
16
|
+
position='left'
|
|
17
|
+
/>
|
|
18
|
+
)
|
|
9
19
|
|
|
10
|
-
|
|
11
|
-
tree = renderer.create(
|
|
12
|
-
<Bubble
|
|
13
|
-
user={{ _id: 1 }}
|
|
14
|
-
currentMessage={{
|
|
15
|
-
_id: 1,
|
|
16
|
-
text: 'test',
|
|
17
|
-
createdAt: 1554744013721,
|
|
18
|
-
user: { _id: 1 },
|
|
19
|
-
}}
|
|
20
|
-
position='left'
|
|
21
|
-
/>
|
|
22
|
-
)
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
expect(tree.toJSON()).toMatchSnapshot()
|
|
20
|
+
expect(toJSON()).toMatchSnapshot()
|
|
26
21
|
})
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import 'react-native'
|
|
2
1
|
import React from 'react'
|
|
3
|
-
import
|
|
2
|
+
import { render } from '@testing-library/react-native'
|
|
4
3
|
|
|
5
4
|
import { Composer } from '../GiftedChat'
|
|
6
5
|
|
|
7
6
|
it('should render <Composer /> and compare with snapshot', () => {
|
|
8
|
-
const
|
|
7
|
+
const { toJSON } = render(<Composer />)
|
|
9
8
|
|
|
10
|
-
expect(
|
|
9
|
+
expect(toJSON()).toMatchSnapshot()
|
|
11
10
|
})
|
|
@@ -1,23 +1,20 @@
|
|
|
1
|
-
import 'react-native'
|
|
2
1
|
import React from 'react'
|
|
3
|
-
import
|
|
2
|
+
import { render } from '@testing-library/react-native'
|
|
4
3
|
|
|
5
4
|
import { Day } from '../GiftedChat'
|
|
6
5
|
import { DEFAULT_TEST_MESSAGE } from './data'
|
|
7
6
|
|
|
8
7
|
describe('Day', () => {
|
|
9
8
|
it('should not render <Day /> and compare with snapshot', () => {
|
|
10
|
-
const
|
|
11
|
-
const tree = component.toJSON()
|
|
9
|
+
const { toJSON } = render(<Day />)
|
|
12
10
|
|
|
13
|
-
expect(
|
|
11
|
+
expect(toJSON()).toMatchSnapshot()
|
|
14
12
|
})
|
|
15
13
|
|
|
16
14
|
it('should render <Day /> and compare with snapshot', () => {
|
|
17
|
-
const
|
|
15
|
+
const { toJSON } = render(
|
|
18
16
|
<Day currentMessage={DEFAULT_TEST_MESSAGE} />
|
|
19
17
|
)
|
|
20
|
-
|
|
21
|
-
expect(tree).toMatchSnapshot()
|
|
18
|
+
expect(toJSON()).toMatchSnapshot()
|
|
22
19
|
})
|
|
23
20
|
})
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { render } from '@testing-library/react-native'
|
|
3
|
+
import { View, Text } from 'react-native'
|
|
4
|
+
import DayAnimated from '../MessageContainer/components/DayAnimated'
|
|
5
|
+
import { DayProps } from '../Day'
|
|
6
|
+
|
|
7
|
+
const mockDaysPositions = { value: {} }
|
|
8
|
+
const mockScrolledY = { value: 0 }
|
|
9
|
+
const mockListHeight = { value: 800 }
|
|
10
|
+
|
|
11
|
+
const mockMessage = {
|
|
12
|
+
_id: 1,
|
|
13
|
+
text: 'Hello',
|
|
14
|
+
createdAt: new Date('2023-01-01'),
|
|
15
|
+
user: { _id: 1, name: 'User 1' },
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
describe('DayAnimated', () => {
|
|
19
|
+
it('should render DayAnimated with default Day component', () => {
|
|
20
|
+
const { toJSON } = render(
|
|
21
|
+
<DayAnimated
|
|
22
|
+
scrolledY={mockScrolledY}
|
|
23
|
+
daysPositions={mockDaysPositions}
|
|
24
|
+
listHeight={mockListHeight}
|
|
25
|
+
messages={[mockMessage]}
|
|
26
|
+
isLoadingEarlier={false}
|
|
27
|
+
/>
|
|
28
|
+
)
|
|
29
|
+
expect(toJSON()).toMatchSnapshot()
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
it('should use custom renderDay when provided', () => {
|
|
33
|
+
const customRenderDay = jest.fn((props: DayProps) => (
|
|
34
|
+
<View testID='custom-day'>
|
|
35
|
+
<Text>Custom Day: {props.createdAt}</Text>
|
|
36
|
+
</View>
|
|
37
|
+
))
|
|
38
|
+
|
|
39
|
+
const { toJSON } = render(
|
|
40
|
+
<DayAnimated
|
|
41
|
+
scrolledY={mockScrolledY}
|
|
42
|
+
daysPositions={mockDaysPositions}
|
|
43
|
+
listHeight={mockListHeight}
|
|
44
|
+
messages={[mockMessage]}
|
|
45
|
+
isLoadingEarlier={false}
|
|
46
|
+
renderDay={customRenderDay}
|
|
47
|
+
/>
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
expect(toJSON()).toMatchSnapshot()
|
|
51
|
+
})
|
|
52
|
+
})
|
|
@@ -1,15 +1,10 @@
|
|
|
1
|
-
import 'react-native'
|
|
2
1
|
import React from 'react'
|
|
3
|
-
import
|
|
2
|
+
import { render } from '@testing-library/react-native'
|
|
4
3
|
|
|
5
4
|
import { GiftedAvatar } from '../GiftedChat'
|
|
6
5
|
|
|
7
6
|
it('should render <GiftedAvatar /> and compare with snapshot', () => {
|
|
8
|
-
|
|
7
|
+
const { toJSON } = render(<GiftedAvatar />)
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
tree = renderer.create(<GiftedAvatar />)
|
|
12
|
-
})
|
|
13
|
-
|
|
14
|
-
expect(tree.toJSON()).toMatchSnapshot()
|
|
9
|
+
expect(toJSON()).toMatchSnapshot()
|
|
15
10
|
})
|