react-native-gifted-chat 3.2.2 → 3.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/README.md +450 -156
  2. package/package.json +9 -8
  3. package/src/Bubble/index.tsx +34 -2
  4. package/src/Bubble/types.ts +17 -4
  5. package/src/Composer.tsx +1 -2
  6. package/src/Day/index.tsx +2 -2
  7. package/src/Day/types.ts +3 -2
  8. package/src/GiftedAvatar.tsx +1 -1
  9. package/src/GiftedChat/index.tsx +109 -23
  10. package/src/GiftedChat/types.ts +9 -3
  11. package/src/InputToolbar.tsx +62 -8
  12. package/src/Message/index.tsx +181 -21
  13. package/src/Message/types.ts +4 -0
  14. package/src/MessageReply.tsx +160 -0
  15. package/src/MessageText.tsx +2 -2
  16. package/src/MessagesContainer/components/DayAnimated/index.tsx +5 -1
  17. package/src/MessagesContainer/components/Item/index.tsx +82 -47
  18. package/src/MessagesContainer/index.tsx +30 -19
  19. package/src/MessagesContainer/styles.ts +2 -0
  20. package/src/MessagesContainer/types.ts +30 -3
  21. package/src/Models.ts +3 -0
  22. package/src/Reply/index.ts +1 -0
  23. package/src/Reply/types.ts +80 -0
  24. package/src/ReplyPreview.tsx +132 -0
  25. package/src/Send.tsx +8 -3
  26. package/src/SystemMessage.tsx +22 -16
  27. package/src/__tests__/MessageReply.test.tsx +54 -0
  28. package/src/__tests__/ReplyPreview.test.tsx +41 -0
  29. package/src/__tests__/__snapshots__/GiftedChat.test.tsx.snap +69 -42
  30. package/src/__tests__/__snapshots__/InputToolbar.test.tsx.snap +11 -15
  31. package/src/__tests__/__snapshots__/MessageImage.test.tsx.snap +24 -18
  32. package/src/__tests__/__snapshots__/MessageReply.test.tsx.snap +181 -0
  33. package/src/__tests__/__snapshots__/ReplyPreview.test.tsx.snap +403 -0
  34. package/src/__tests__/__snapshots__/Send.test.tsx.snap +3 -0
  35. package/src/__tests__/__snapshots__/SystemMessage.test.tsx.snap +36 -25
  36. package/src/components/MessageReply.tsx +156 -0
  37. package/src/components/ReplyPreview.tsx +230 -0
  38. package/src/index.ts +6 -1
  39. package/src/types.ts +17 -16
  40. package/src/utils.ts +11 -3
  41. package/CHANGELOG.md +0 -364
  42. package/src/reanimatedCompat.ts +0 -27
@@ -0,0 +1,403 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`should render <ReplyPreview /> and compare with snapshot 1`] = `
4
+ <View
5
+ collapsable={false}
6
+ jestAnimatedProps={
7
+ {
8
+ "value": {},
9
+ }
10
+ }
11
+ jestAnimatedStyle={
12
+ {
13
+ "value": {
14
+ "height": 0,
15
+ "opacity": 0,
16
+ "transform": [
17
+ {
18
+ "translateY": 10,
19
+ },
20
+ ],
21
+ },
22
+ }
23
+ }
24
+ jestInlineStyle={
25
+ [
26
+ {
27
+ "overflow": "hidden",
28
+ },
29
+ ]
30
+ }
31
+ nativeID="0"
32
+ style={
33
+ [
34
+ {
35
+ "overflow": "hidden",
36
+ },
37
+ {
38
+ "height": 0,
39
+ "opacity": 0,
40
+ "transform": [
41
+ {
42
+ "translateY": 10,
43
+ },
44
+ ],
45
+ },
46
+ ]
47
+ }
48
+ >
49
+ <View
50
+ onLayout={[Function]}
51
+ style={
52
+ [
53
+ {
54
+ "borderRadius": 8,
55
+ "flexDirection": "row",
56
+ "marginBottom": 8,
57
+ "marginHorizontal": 10,
58
+ "overflow": "hidden",
59
+ },
60
+ {
61
+ "backgroundColor": "#e9e9eb",
62
+ },
63
+ undefined,
64
+ ]
65
+ }
66
+ >
67
+ <View
68
+ style={
69
+ {
70
+ "backgroundColor": "#0084ff",
71
+ "borderTopLeftRadius": 4,
72
+ "height": "100%",
73
+ "width": 4,
74
+ }
75
+ }
76
+ />
77
+ <View
78
+ style={
79
+ {
80
+ "flex": 1,
81
+ "paddingHorizontal": 10,
82
+ "paddingVertical": 8,
83
+ }
84
+ }
85
+ >
86
+ <View
87
+ style={
88
+ {
89
+ "alignItems": "center",
90
+ "flexDirection": "row",
91
+ }
92
+ }
93
+ >
94
+ <View
95
+ style={
96
+ {
97
+ "flex": 1,
98
+ }
99
+ }
100
+ >
101
+ <Text
102
+ numberOfLines={1}
103
+ style={
104
+ {
105
+ "color": "#0084ff",
106
+ "fontSize": 13,
107
+ "fontWeight": "600",
108
+ "marginBottom": 2,
109
+ }
110
+ }
111
+ >
112
+ Replying to
113
+ John Doe
114
+ </Text>
115
+ <Text
116
+ numberOfLines={2}
117
+ style={
118
+ [
119
+ {
120
+ "fontSize": 14,
121
+ },
122
+ {
123
+ "color": "#333",
124
+ },
125
+ undefined,
126
+ ]
127
+ }
128
+ >
129
+ Original message to reply to
130
+ </Text>
131
+ </View>
132
+ </View>
133
+ </View>
134
+ <View
135
+ accessibilityState={
136
+ {
137
+ "busy": undefined,
138
+ "checked": undefined,
139
+ "disabled": undefined,
140
+ "expanded": undefined,
141
+ "selected": undefined,
142
+ }
143
+ }
144
+ accessibilityValue={
145
+ {
146
+ "max": undefined,
147
+ "min": undefined,
148
+ "now": undefined,
149
+ "text": undefined,
150
+ }
151
+ }
152
+ accessible={true}
153
+ collapsable={false}
154
+ focusable={true}
155
+ hitSlop={8}
156
+ onBlur={[Function]}
157
+ onClick={[Function]}
158
+ onFocus={[Function]}
159
+ onResponderGrant={[Function]}
160
+ onResponderMove={[Function]}
161
+ onResponderRelease={[Function]}
162
+ onResponderTerminate={[Function]}
163
+ onResponderTerminationRequest={[Function]}
164
+ onStartShouldSetResponder={[Function]}
165
+ style={
166
+ {
167
+ "alignItems": "center",
168
+ "borderRadius": 12,
169
+ "height": 24,
170
+ "justifyContent": "center",
171
+ "width": 24,
172
+ }
173
+ }
174
+ >
175
+ <Text
176
+ style={
177
+ [
178
+ {
179
+ "fontSize": 18,
180
+ "fontWeight": "600",
181
+ },
182
+ {
183
+ "color": "#333",
184
+ },
185
+ ]
186
+ }
187
+ >
188
+ ×
189
+ </Text>
190
+ </View>
191
+ </View>
192
+ </View>
193
+ `;
194
+
195
+ exports[`should render <ReplyPreview /> with image and compare with snapshot 1`] = `
196
+ <View
197
+ collapsable={false}
198
+ jestAnimatedProps={
199
+ {
200
+ "value": {},
201
+ }
202
+ }
203
+ jestAnimatedStyle={
204
+ {
205
+ "value": {
206
+ "height": 0,
207
+ "opacity": 0,
208
+ "transform": [
209
+ {
210
+ "translateY": 10,
211
+ },
212
+ ],
213
+ },
214
+ }
215
+ }
216
+ jestInlineStyle={
217
+ [
218
+ {
219
+ "overflow": "hidden",
220
+ },
221
+ ]
222
+ }
223
+ nativeID="1"
224
+ style={
225
+ [
226
+ {
227
+ "overflow": "hidden",
228
+ },
229
+ {
230
+ "height": 0,
231
+ "opacity": 0,
232
+ "transform": [
233
+ {
234
+ "translateY": 10,
235
+ },
236
+ ],
237
+ },
238
+ ]
239
+ }
240
+ >
241
+ <View
242
+ onLayout={[Function]}
243
+ style={
244
+ [
245
+ {
246
+ "borderRadius": 8,
247
+ "flexDirection": "row",
248
+ "marginBottom": 8,
249
+ "marginHorizontal": 10,
250
+ "overflow": "hidden",
251
+ },
252
+ {
253
+ "backgroundColor": "#e9e9eb",
254
+ },
255
+ undefined,
256
+ ]
257
+ }
258
+ >
259
+ <View
260
+ style={
261
+ {
262
+ "backgroundColor": "#0084ff",
263
+ "borderTopLeftRadius": 4,
264
+ "height": "100%",
265
+ "width": 4,
266
+ }
267
+ }
268
+ />
269
+ <View
270
+ style={
271
+ {
272
+ "flex": 1,
273
+ "paddingHorizontal": 10,
274
+ "paddingVertical": 8,
275
+ }
276
+ }
277
+ >
278
+ <View
279
+ style={
280
+ {
281
+ "alignItems": "center",
282
+ "flexDirection": "row",
283
+ }
284
+ }
285
+ >
286
+ <Image
287
+ source={
288
+ {
289
+ "uri": "https://example.com/image.jpg",
290
+ }
291
+ }
292
+ style={
293
+ [
294
+ {
295
+ "borderRadius": 4,
296
+ "height": 40,
297
+ "marginRight": 8,
298
+ "width": 40,
299
+ },
300
+ undefined,
301
+ ]
302
+ }
303
+ />
304
+ <View
305
+ style={
306
+ {
307
+ "flex": 1,
308
+ }
309
+ }
310
+ >
311
+ <Text
312
+ numberOfLines={1}
313
+ style={
314
+ {
315
+ "color": "#0084ff",
316
+ "fontSize": 13,
317
+ "fontWeight": "600",
318
+ "marginBottom": 2,
319
+ }
320
+ }
321
+ >
322
+ Replying to
323
+ John Doe
324
+ </Text>
325
+ <Text
326
+ numberOfLines={2}
327
+ style={
328
+ [
329
+ {
330
+ "fontSize": 14,
331
+ },
332
+ {
333
+ "color": "#333",
334
+ },
335
+ undefined,
336
+ ]
337
+ }
338
+ >
339
+ Original message to reply to
340
+ </Text>
341
+ </View>
342
+ </View>
343
+ </View>
344
+ <View
345
+ accessibilityState={
346
+ {
347
+ "busy": undefined,
348
+ "checked": undefined,
349
+ "disabled": undefined,
350
+ "expanded": undefined,
351
+ "selected": undefined,
352
+ }
353
+ }
354
+ accessibilityValue={
355
+ {
356
+ "max": undefined,
357
+ "min": undefined,
358
+ "now": undefined,
359
+ "text": undefined,
360
+ }
361
+ }
362
+ accessible={true}
363
+ collapsable={false}
364
+ focusable={true}
365
+ hitSlop={8}
366
+ onBlur={[Function]}
367
+ onClick={[Function]}
368
+ onFocus={[Function]}
369
+ onResponderGrant={[Function]}
370
+ onResponderMove={[Function]}
371
+ onResponderRelease={[Function]}
372
+ onResponderTerminate={[Function]}
373
+ onResponderTerminationRequest={[Function]}
374
+ onStartShouldSetResponder={[Function]}
375
+ style={
376
+ {
377
+ "alignItems": "center",
378
+ "borderRadius": 12,
379
+ "height": 24,
380
+ "justifyContent": "center",
381
+ "width": 24,
382
+ }
383
+ }
384
+ >
385
+ <Text
386
+ style={
387
+ [
388
+ {
389
+ "fontSize": 18,
390
+ "fontWeight": "600",
391
+ },
392
+ {
393
+ "color": "#333",
394
+ },
395
+ ]
396
+ }
397
+ >
398
+ ×
399
+ </Text>
400
+ </View>
401
+ </View>
402
+ </View>
403
+ `;
@@ -23,6 +23,7 @@ exports[`Send should always render <Send /> and compare with snapshot 1`] = `
23
23
  undefined,
24
24
  ]
25
25
  }
26
+ nativeID="1"
26
27
  pointerEvents="auto"
27
28
  style={
28
29
  [
@@ -93,6 +94,7 @@ exports[`Send should not render <Send /> and compare with snapshot 1`] = `
93
94
  undefined,
94
95
  ]
95
96
  }
97
+ nativeID="0"
96
98
  pointerEvents="none"
97
99
  style={
98
100
  [
@@ -163,6 +165,7 @@ exports[`Send should render <Send /> where there is input and compare with snaps
163
165
  undefined,
164
166
  ]
165
167
  }
168
+ nativeID="2"
166
169
  pointerEvents="auto"
167
170
  style={
168
171
  [
@@ -10,17 +10,10 @@ exports[`SystemMessage should render <SystemMessage /> and compare with snapshot
10
10
  "flex": 1,
11
11
  },
12
12
  {
13
- "alignItems": "flex-end",
14
- "backgroundColor": "rgba(0,0,0,0.05)",
15
- "borderColor": "rgba(0,0,0,0.1)",
16
- "borderRadius": 20,
17
- "borderWidth": 1,
13
+ "alignItems": "center",
18
14
  "marginHorizontal": 10,
19
15
  "marginVertical": 5,
20
- "paddingHorizontal": 10,
21
- "paddingVertical": 10,
22
16
  },
23
- undefined,
24
17
  ]
25
18
  }
26
19
  >
@@ -28,39 +21,57 @@ exports[`SystemMessage should render <SystemMessage /> and compare with snapshot
28
21
  style={
29
22
  [
30
23
  {
31
- "marginHorizontal": 10,
32
- "marginVertical": 5,
24
+ "backgroundColor": "rgba(0,0,0,0.05)",
25
+ "borderColor": "rgba(0,0,0,0.1)",
26
+ "borderRadius": 20,
27
+ "borderWidth": 1,
28
+ "maxWidth": "70%",
29
+ "paddingHorizontal": 10,
30
+ "paddingVertical": 10,
33
31
  },
34
- [
35
- {
36
- "marginHorizontal": 0,
37
- "marginVertical": 0,
38
- },
39
- undefined,
40
- ],
32
+ undefined,
41
33
  ]
42
34
  }
43
35
  >
44
- <Text
36
+ <View
45
37
  style={
46
38
  [
47
39
  {
48
- "color": "black",
40
+ "marginHorizontal": 10,
41
+ "marginVertical": 5,
49
42
  },
50
- undefined,
51
43
  [
52
44
  {
53
- "backgroundColor": "transparent",
54
- "fontSize": 12,
55
- "fontWeight": "300",
45
+ "marginHorizontal": 0,
46
+ "marginVertical": 0,
56
47
  },
57
48
  undefined,
58
49
  ],
59
50
  ]
60
51
  }
61
52
  >
62
- test
63
- </Text>
53
+ <Text
54
+ style={
55
+ [
56
+ {
57
+ "color": "black",
58
+ },
59
+ undefined,
60
+ [
61
+ {
62
+ "backgroundColor": "transparent",
63
+ "fontSize": 12,
64
+ "fontWeight": "300",
65
+ "textAlign": "center",
66
+ },
67
+ undefined,
68
+ ],
69
+ ]
70
+ }
71
+ >
72
+ test
73
+ </Text>
74
+ </View>
64
75
  </View>
65
76
  </View>
66
77
  `;
@@ -0,0 +1,156 @@
1
+ import React, { useMemo } from 'react'
2
+ import {
3
+ Image,
4
+ ImageStyle,
5
+ Pressable,
6
+ StyleProp,
7
+ StyleSheet,
8
+ Text,
9
+ TextStyle,
10
+ View,
11
+ ViewStyle,
12
+ } from 'react-native'
13
+
14
+ import { IMessage, ReplyMessage } from '../Models'
15
+ import { isSameUser } from '../utils'
16
+
17
+ export interface MessageReplyProps<TMessage extends IMessage = IMessage> {
18
+ /** The reply message to display */
19
+ replyMessage: ReplyMessage
20
+ /** The current message containing the reply */
21
+ currentMessage: TMessage
22
+ /** Position of the bubble (left or right) */
23
+ position: 'left' | 'right'
24
+ /** Container style for the reply */
25
+ containerStyle?: StyleProp<ViewStyle>
26
+ /** Container style for left position */
27
+ containerStyleLeft?: StyleProp<ViewStyle>
28
+ /** Container style for right position */
29
+ containerStyleRight?: StyleProp<ViewStyle>
30
+ /** Text style for the reply */
31
+ textStyle?: StyleProp<TextStyle>
32
+ /** Text style for left position */
33
+ textStyleLeft?: StyleProp<TextStyle>
34
+ /** Text style for right position */
35
+ textStyleRight?: StyleProp<TextStyle>
36
+ /** Image style for the reply */
37
+ imageStyle?: StyleProp<ImageStyle>
38
+ /** Callback when reply is pressed */
39
+ onPress?: (replyMessage: ReplyMessage) => void
40
+ }
41
+
42
+ const styles = StyleSheet.create({
43
+ container: {
44
+ borderRadius: 8,
45
+ marginBottom: 4,
46
+ paddingHorizontal: 10,
47
+ paddingVertical: 6,
48
+ },
49
+ containerLeft: {
50
+ backgroundColor: 'rgba(0, 0, 0, 0.06)',
51
+ borderLeftColor: '#0084ff',
52
+ borderLeftWidth: 3,
53
+ },
54
+ containerRight: {
55
+ backgroundColor: 'rgba(255, 255, 255, 0.15)',
56
+ borderLeftColor: 'rgba(255, 255, 255, 0.6)',
57
+ borderLeftWidth: 3,
58
+ },
59
+ image: {
60
+ borderRadius: 4,
61
+ height: 40,
62
+ marginTop: 4,
63
+ width: 40,
64
+ },
65
+ text: {
66
+ fontSize: 13,
67
+ },
68
+ textLeft: {
69
+ color: '#333',
70
+ },
71
+ textRight: {
72
+ color: 'rgba(255, 255, 255, 0.9)',
73
+ },
74
+ username: {
75
+ fontWeight: '600',
76
+ marginBottom: 2,
77
+ },
78
+ usernameLeft: {
79
+ color: '#0084ff',
80
+ },
81
+ usernameRight: {
82
+ color: 'rgba(255, 255, 255, 0.9)',
83
+ },
84
+ })
85
+
86
+ export function MessageReply<TMessage extends IMessage = IMessage> ({
87
+ replyMessage,
88
+ currentMessage,
89
+ position,
90
+ containerStyle,
91
+ containerStyleLeft,
92
+ containerStyleRight,
93
+ textStyle,
94
+ textStyleLeft,
95
+ textStyleRight,
96
+ imageStyle,
97
+ onPress,
98
+ }: MessageReplyProps<TMessage>) {
99
+ const isCurrentUser = useMemo(
100
+ () => isSameUser(currentMessage, { user: replyMessage.user } as TMessage),
101
+ [currentMessage, replyMessage.user]
102
+ )
103
+
104
+ const displayName = useMemo(() => {
105
+ if (isCurrentUser)
106
+ return 'You'
107
+
108
+ return replyMessage.user?.name || 'Unknown'
109
+ }, [isCurrentUser, replyMessage.user?.name])
110
+
111
+ const handlePress = () => {
112
+ onPress?.(replyMessage)
113
+ }
114
+
115
+ const containerStyles = [
116
+ styles.container,
117
+ position === 'left' ? styles.containerLeft : styles.containerRight,
118
+ containerStyle,
119
+ position === 'left' ? containerStyleLeft : containerStyleRight,
120
+ ]
121
+
122
+ const usernameStyles = [
123
+ styles.username,
124
+ position === 'left' ? styles.usernameLeft : styles.usernameRight,
125
+ textStyle,
126
+ position === 'left' ? textStyleLeft : textStyleRight,
127
+ ]
128
+
129
+ const textStyles = [
130
+ styles.text,
131
+ position === 'left' ? styles.textLeft : styles.textRight,
132
+ textStyle,
133
+ position === 'left' ? textStyleLeft : textStyleRight,
134
+ ]
135
+
136
+ return (
137
+ <Pressable onPress={handlePress}>
138
+ <View style={containerStyles}>
139
+ <Text style={usernameStyles} numberOfLines={1}>
140
+ {displayName}
141
+ </Text>
142
+ {replyMessage.text && (
143
+ <Text style={textStyles} numberOfLines={2}>
144
+ {replyMessage.text}
145
+ </Text>
146
+ )}
147
+ {replyMessage.image && (
148
+ <Image
149
+ source={{ uri: replyMessage.image }}
150
+ style={[styles.image, imageStyle]}
151
+ />
152
+ )}
153
+ </View>
154
+ </Pressable>
155
+ )
156
+ }