react-native-gifted-chat 2.8.2-alpha.0 → 2.8.2-alpha.2

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 (203) hide show
  1. package/README.md +51 -31
  2. package/package.json +28 -30
  3. package/src/Actions.tsx +1 -1
  4. package/src/Avatar.tsx +1 -1
  5. package/src/Bubble/index.tsx +24 -20
  6. package/src/Bubble/types.ts +7 -6
  7. package/src/Composer.tsx +19 -26
  8. package/src/Constant.ts +0 -1
  9. package/src/Day/index.tsx +3 -3
  10. package/src/GiftedAvatar.tsx +31 -38
  11. package/src/GiftedChat/index.tsx +59 -106
  12. package/src/GiftedChat/styles.ts +3 -0
  13. package/src/GiftedChat/types.ts +17 -67
  14. package/src/InputToolbar.tsx +27 -10
  15. package/src/LoadEarlier.tsx +22 -20
  16. package/src/Message/index.tsx +4 -18
  17. package/src/Message/types.ts +2 -2
  18. package/src/MessageAudio.tsx +19 -7
  19. package/src/MessageContainer/components/DayAnimated/index.tsx +16 -11
  20. package/src/MessageContainer/components/Item/index.tsx +10 -4
  21. package/src/MessageContainer/components/Item/types.ts +1 -1
  22. package/src/MessageContainer/index.tsx +57 -38
  23. package/src/MessageContainer/types.ts +32 -7
  24. package/src/MessageImage.tsx +132 -18
  25. package/src/MessageText.tsx +24 -64
  26. package/src/MessageVideo.tsx +19 -7
  27. package/src/QuickReplies.tsx +19 -12
  28. package/src/Send.tsx +10 -5
  29. package/src/SystemMessage.tsx +10 -3
  30. package/src/Time.tsx +10 -3
  31. package/src/TypingIndicator/index.tsx +4 -3
  32. package/src/TypingIndicator/types.ts +3 -0
  33. package/src/__tests__/Actions.test.tsx +3 -4
  34. package/src/__tests__/Avatar.test.tsx +5 -6
  35. package/src/__tests__/Bubble.test.tsx +14 -19
  36. package/src/__tests__/Composer.test.tsx +3 -4
  37. package/src/__tests__/Day.test.tsx +5 -8
  38. package/src/__tests__/DayAnimated.test.tsx +12 -14
  39. package/src/__tests__/GiftedAvatar.test.tsx +3 -8
  40. package/src/__tests__/GiftedChat.test.tsx +34 -43
  41. package/src/__tests__/InputToolbar.test.tsx +3 -4
  42. package/src/__tests__/LoadEarlier.test.tsx +3 -4
  43. package/src/__tests__/Message.test.tsx +51 -58
  44. package/src/__tests__/MessageContainer.test.tsx +39 -5
  45. package/src/__tests__/MessageImage.test.tsx +12 -15
  46. package/src/__tests__/MessageText.test.tsx +7 -4
  47. package/src/__tests__/Send.test.tsx +7 -8
  48. package/src/__tests__/SystemMessage.test.tsx +12 -15
  49. package/src/__tests__/Time.test.tsx +5 -8
  50. package/src/__tests__/__snapshots__/Actions.test.tsx.snap +39 -7
  51. package/src/__tests__/__snapshots__/Bubble.test.tsx.snap +48 -50
  52. package/src/__tests__/__snapshots__/Composer.test.tsx.snap +1 -2
  53. package/src/__tests__/__snapshots__/Constant.test.tsx.snap +0 -1
  54. package/src/__tests__/__snapshots__/GiftedChat.test.tsx.snap +20 -22
  55. package/src/__tests__/__snapshots__/InputToolbar.test.tsx.snap +2 -2
  56. package/src/__tests__/__snapshots__/LoadEarlier.test.tsx.snap +37 -6
  57. package/src/__tests__/__snapshots__/Message.test.tsx.snap +146 -150
  58. package/src/__tests__/__snapshots__/MessageImage.test.tsx.snap +32 -11
  59. package/src/__tests__/__snapshots__/MessageText.test.tsx.snap +12 -8
  60. package/src/__tests__/__snapshots__/Send.test.tsx.snap +72 -10
  61. package/src/components/TouchableOpacity.tsx +45 -0
  62. package/src/reanimatedCompat.ts +27 -0
  63. package/src/types.ts +4 -2
  64. package/src/utils.ts +2 -2
  65. package/lib/Actions.d.ts +0 -14
  66. package/lib/Actions.js +0 -57
  67. package/lib/Actions.js.map +0 -1
  68. package/lib/Avatar.d.ts +0 -18
  69. package/lib/Avatar.js +0 -93
  70. package/lib/Avatar.js.map +0 -1
  71. package/lib/Bubble/index.d.ts +0 -6
  72. package/lib/Bubble/index.js +0 -242
  73. package/lib/Bubble/index.js.map +0 -1
  74. package/lib/Bubble/styles.d.ts +0 -69
  75. package/lib/Bubble/styles.js +0 -72
  76. package/lib/Bubble/styles.js.map +0 -1
  77. package/lib/Bubble/types.d.ts +0 -47
  78. package/lib/Bubble/types.js +0 -2
  79. package/lib/Bubble/types.js.map +0 -1
  80. package/lib/Color.d.ts +0 -18
  81. package/lib/Color.js +0 -18
  82. package/lib/Color.js.map +0 -1
  83. package/lib/Composer.d.ts +0 -20
  84. package/lib/Composer.js +0 -60
  85. package/lib/Composer.js.map +0 -1
  86. package/lib/Constant.d.ts +0 -10
  87. package/lib/Constant.js +0 -17
  88. package/lib/Constant.js.map +0 -1
  89. package/lib/Day/index.d.ts +0 -4
  90. package/lib/Day/index.js +0 -39
  91. package/lib/Day/index.js.map +0 -1
  92. package/lib/Day/styles.d.ts +0 -20
  93. package/lib/Day/styles.js +0 -22
  94. package/lib/Day/styles.js.map +0 -1
  95. package/lib/Day/types.d.ts +0 -9
  96. package/lib/Day/types.js +0 -2
  97. package/lib/Day/types.js.map +0 -1
  98. package/lib/GiftedAvatar.d.ts +0 -11
  99. package/lib/GiftedAvatar.js +0 -104
  100. package/lib/GiftedAvatar.js.map +0 -1
  101. package/lib/GiftedChat/index.d.ts +0 -26
  102. package/lib/GiftedChat/index.js +0 -317
  103. package/lib/GiftedChat/index.js.map +0 -1
  104. package/lib/GiftedChat/styles.d.ts +0 -6
  105. package/lib/GiftedChat/styles.js +0 -7
  106. package/lib/GiftedChat/styles.js.map +0 -1
  107. package/lib/GiftedChat/types.d.ts +0 -112
  108. package/lib/GiftedChat/types.js +0 -2
  109. package/lib/GiftedChat/types.js.map +0 -1
  110. package/lib/GiftedChatContext.d.ts +0 -9
  111. package/lib/GiftedChatContext.js +0 -9
  112. package/lib/GiftedChatContext.js.map +0 -1
  113. package/lib/InputToolbar.d.ts +0 -23
  114. package/lib/InputToolbar.js +0 -56
  115. package/lib/InputToolbar.js.map +0 -1
  116. package/lib/LoadEarlier.d.ts +0 -14
  117. package/lib/LoadEarlier.js +0 -45
  118. package/lib/LoadEarlier.js.map +0 -1
  119. package/lib/Message/index.d.ts +0 -6
  120. package/lib/Message/index.js +0 -80
  121. package/lib/Message/index.js.map +0 -1
  122. package/lib/Message/styles.d.ts +0 -21
  123. package/lib/Message/styles.js +0 -22
  124. package/lib/Message/styles.js.map +0 -1
  125. package/lib/Message/types.d.ts +0 -22
  126. package/lib/Message/types.js +0 -2
  127. package/lib/Message/types.js.map +0 -1
  128. package/lib/MessageAudio.d.ts +0 -2
  129. package/lib/MessageAudio.js +0 -14
  130. package/lib/MessageAudio.js.map +0 -1
  131. package/lib/MessageContainer/components/DayAnimated/index.d.ts +0 -5
  132. package/lib/MessageContainer/components/DayAnimated/index.js +0 -85
  133. package/lib/MessageContainer/components/DayAnimated/index.js.map +0 -1
  134. package/lib/MessageContainer/components/DayAnimated/styles.d.ts +0 -11
  135. package/lib/MessageContainer/components/DayAnimated/styles.js +0 -12
  136. package/lib/MessageContainer/components/DayAnimated/styles.js.map +0 -1
  137. package/lib/MessageContainer/components/DayAnimated/types.d.ts +0 -17
  138. package/lib/MessageContainer/components/DayAnimated/types.js +0 -2
  139. package/lib/MessageContainer/components/DayAnimated/types.js.map +0 -1
  140. package/lib/MessageContainer/components/Item/index.d.ts +0 -23
  141. package/lib/MessageContainer/components/Item/index.js +0 -88
  142. package/lib/MessageContainer/components/Item/index.js.map +0 -1
  143. package/lib/MessageContainer/components/Item/types.d.ts +0 -17
  144. package/lib/MessageContainer/components/Item/types.js +0 -2
  145. package/lib/MessageContainer/components/Item/types.js.map +0 -1
  146. package/lib/MessageContainer/index.d.ts +0 -6
  147. package/lib/MessageContainer/index.js +0 -235
  148. package/lib/MessageContainer/index.js.map +0 -1
  149. package/lib/MessageContainer/styles.d.ts +0 -35
  150. package/lib/MessageContainer/styles.js +0 -32
  151. package/lib/MessageContainer/styles.js.map +0 -1
  152. package/lib/MessageContainer/types.d.ts +0 -51
  153. package/lib/MessageContainer/types.js +0 -2
  154. package/lib/MessageContainer/types.js.map +0 -1
  155. package/lib/MessageImage.d.ts +0 -13
  156. package/lib/MessageImage.js +0 -30
  157. package/lib/MessageImage.js.map +0 -1
  158. package/lib/MessageText.d.ts +0 -19
  159. package/lib/MessageText.js +0 -69
  160. package/lib/MessageText.js.map +0 -1
  161. package/lib/MessageVideo.d.ts +0 -2
  162. package/lib/MessageVideo.js +0 -14
  163. package/lib/MessageVideo.js.map +0 -1
  164. package/lib/QuickReplies.d.ts +0 -15
  165. package/lib/QuickReplies.js +0 -101
  166. package/lib/QuickReplies.js.map +0 -1
  167. package/lib/Send.d.ts +0 -15
  168. package/lib/Send.js +0 -34
  169. package/lib/Send.js.map +0 -1
  170. package/lib/SystemMessage.d.ts +0 -11
  171. package/lib/SystemMessage.js +0 -27
  172. package/lib/SystemMessage.js.map +0 -1
  173. package/lib/Time.d.ts +0 -11
  174. package/lib/Time.js +0 -56
  175. package/lib/Time.js.map +0 -1
  176. package/lib/TypingIndicator/index.d.ts +0 -5
  177. package/lib/TypingIndicator/index.js +0 -94
  178. package/lib/TypingIndicator/index.js.map +0 -1
  179. package/lib/TypingIndicator/styles.d.ts +0 -20
  180. package/lib/TypingIndicator/styles.js +0 -22
  181. package/lib/TypingIndicator/styles.js.map +0 -1
  182. package/lib/TypingIndicator/types.d.ts +0 -3
  183. package/lib/TypingIndicator/types.js +0 -2
  184. package/lib/TypingIndicator/types.js.map +0 -1
  185. package/lib/hooks/useUpdateLayoutEffect.d.ts +0 -8
  186. package/lib/hooks/useUpdateLayoutEffect.js +0 -17
  187. package/lib/hooks/useUpdateLayoutEffect.js.map +0 -1
  188. package/lib/index.d.ts +0 -4
  189. package/lib/index.js +0 -5
  190. package/lib/index.js.map +0 -1
  191. package/lib/logging.d.ts +0 -2
  192. package/lib/logging.js +0 -5
  193. package/lib/logging.js.map +0 -1
  194. package/lib/styles.d.ts +0 -10
  195. package/lib/styles.js +0 -11
  196. package/lib/styles.js.map +0 -1
  197. package/lib/types.d.ts +0 -67
  198. package/lib/types.js +0 -2
  199. package/lib/types.js.map +0 -1
  200. package/lib/utils.d.ts +0 -5
  201. package/lib/utils.js +0 -83
  202. package/lib/utils.js.map +0 -1
  203. package/src/__tests__/__snapshots__/MessageContainer.test.tsx.snap +0 -108
@@ -1,10 +1,10 @@
1
1
  import React, { useMemo } from 'react'
2
- import { StyleSheet, View, StyleProp, ViewStyle } from 'react-native'
2
+ import { StyleSheet, View, StyleProp, ViewStyle, useColorScheme } from 'react-native'
3
3
 
4
- import { Composer, ComposerProps } from './Composer'
5
- import { Send, SendProps } from './Send'
6
4
  import { Actions, ActionsProps } from './Actions'
7
5
  import Color from './Color'
6
+ import { Composer, ComposerProps } from './Composer'
7
+ import { Send, SendProps } from './Send'
8
8
  import { IMessage } from './types'
9
9
 
10
10
  export interface InputToolbarProps<TMessage extends IMessage> {
@@ -38,6 +38,8 @@ export function InputToolbar<TMessage extends IMessage = IMessage> (
38
38
  containerStyle,
39
39
  } = props
40
40
 
41
+ const colorScheme = useColorScheme()
42
+
41
43
  const actionsFragment = useMemo(() => {
42
44
  const props = {
43
45
  onPressActionButton,
@@ -69,18 +71,29 @@ export function InputToolbar<TMessage extends IMessage = IMessage> (
69
71
  )
70
72
  }, [renderComposer, props])
71
73
 
74
+ const sendFragment = useMemo(() => {
75
+ return renderSend?.(props) || <Send {...props} />
76
+ }, [renderSend, props])
77
+
78
+ const accessoryFragment = useMemo(() => {
79
+ if (!renderAccessory)
80
+ return null
81
+
82
+ return (
83
+ <View style={[styles.accessory, props.accessoryStyle]}>
84
+ {renderAccessory(props)}
85
+ </View>
86
+ )
87
+ }, [renderAccessory, props])
88
+
72
89
  return (
73
- <View style={[styles.container, containerStyle]}>
90
+ <View style={[styles.container, styles[`container_${colorScheme}`], containerStyle]}>
74
91
  <View style={[styles.primary, props.primaryStyle]}>
75
92
  {actionsFragment}
76
93
  {composerFragment}
77
- {renderSend?.(props) || <Send {...props} />}
94
+ {sendFragment}
78
95
  </View>
79
- {renderAccessory && (
80
- <View style={[styles.accessory, props.accessoryStyle]}>
81
- {renderAccessory(props)}
82
- </View>
83
- )}
96
+ {accessoryFragment}
84
97
  </View>
85
98
  )
86
99
  }
@@ -91,6 +104,10 @@ const styles = StyleSheet.create({
91
104
  borderTopColor: Color.defaultColor,
92
105
  backgroundColor: Color.white,
93
106
  },
107
+ container_dark: {
108
+ backgroundColor: '#1a1a1a',
109
+ borderTopColor: '#444',
110
+ },
94
111
  primary: {
95
112
  flexDirection: 'row',
96
113
  alignItems: 'flex-end',
@@ -1,16 +1,16 @@
1
- import React from 'react'
1
+ import React, { useMemo } from 'react'
2
2
  import {
3
3
  ActivityIndicator,
4
4
  Platform,
5
5
  StyleSheet,
6
6
  Text,
7
- TouchableOpacity,
8
7
  View,
9
8
  StyleProp,
10
9
  ViewStyle,
11
10
  TextStyle,
12
11
  } from 'react-native'
13
12
  import Color from './Color'
13
+ import { TouchableOpacity } from './components/TouchableOpacity'
14
14
  import stylesCommon from './styles'
15
15
 
16
16
  const styles = StyleSheet.create({
@@ -52,7 +52,7 @@ export interface LoadEarlierProps {
52
52
  onLoadEarlier?(): void
53
53
  }
54
54
 
55
- export function LoadEarlier ({
55
+ export const LoadEarlier: React.FC<LoadEarlierProps> = ({
56
56
  isLoadingEarlier = false,
57
57
  onLoadEarlier = () => {},
58
58
  label = 'Load earlier messages',
@@ -62,7 +62,24 @@ export function LoadEarlier ({
62
62
  activityIndicatorColor = 'white',
63
63
  activityIndicatorSize = 'small',
64
64
  activityIndicatorStyle,
65
- }: LoadEarlierProps): React.ReactElement {
65
+ }) => {
66
+ const loadingContent = useMemo(() => (
67
+ <View>
68
+ <Text style={[styles.text, textStyle, { opacity: 0 }]}>
69
+ {label}
70
+ </Text>
71
+ <ActivityIndicator
72
+ color={activityIndicatorColor!}
73
+ size={activityIndicatorSize!}
74
+ style={[styles.activityIndicator, activityIndicatorStyle]}
75
+ />
76
+ </View>
77
+ ), [label, textStyle, activityIndicatorColor, activityIndicatorSize, activityIndicatorStyle])
78
+
79
+ const labelContent = useMemo(() => (
80
+ <Text style={[styles.text, textStyle]}>{label}</Text>
81
+ ), [label, textStyle])
82
+
66
83
  return (
67
84
  <TouchableOpacity
68
85
  style={[styles.container, containerStyle]}
@@ -71,22 +88,7 @@ export function LoadEarlier ({
71
88
  accessibilityRole='button'
72
89
  >
73
90
  <View style={[stylesCommon.centerItems, styles.wrapper, wrapperStyle]}>
74
- {isLoadingEarlier
75
- ? (
76
- <View>
77
- <Text style={[styles.text, textStyle, { opacity: 0 }]}>
78
- {label}
79
- </Text>
80
- <ActivityIndicator
81
- color={activityIndicatorColor!}
82
- size={activityIndicatorSize!}
83
- style={[styles.activityIndicator, activityIndicatorStyle]}
84
- />
85
- </View>
86
- )
87
- : (
88
- <Text style={[styles.text, textStyle]}>{label}</Text>
89
- )}
91
+ {isLoadingEarlier ? loadingContent : labelContent}
90
92
  </View>
91
93
  </TouchableOpacity>
92
94
  )
@@ -1,19 +1,18 @@
1
1
  import React, { memo, useCallback } from 'react'
2
2
  import { View } from 'react-native'
3
- import isEqual from 'lodash.isequal'
4
3
 
5
4
  import { Avatar } from '../Avatar'
6
5
  import Bubble from '../Bubble'
7
6
  import { SystemMessage } from '../SystemMessage'
8
7
 
9
- import { isSameUser } from '../utils'
10
8
  import { IMessage } from '../types'
11
- import { MessageProps } from './types'
9
+ import { isSameUser } from '../utils'
12
10
  import styles from './styles'
11
+ import { MessageProps } from './types'
13
12
 
14
13
  export * from './types'
15
14
 
16
- let Message: React.FC<MessageProps<IMessage>> = (props: MessageProps<IMessage>) => {
15
+ const Message: React.FC<MessageProps<IMessage>> = (props: MessageProps<IMessage>) => {
17
16
  const {
18
17
  currentMessage,
19
18
  renderBubble: renderBubbleProp,
@@ -113,17 +112,4 @@ let Message: React.FC<MessageProps<IMessage>> = (props: MessageProps<IMessage>)
113
112
  )
114
113
  }
115
114
 
116
- Message = memo(Message, (props, nextProps) => {
117
- const shouldUpdate =
118
- props.shouldUpdateMessage?.(props, nextProps) ||
119
- !isEqual(props.currentMessage!, nextProps.currentMessage!) ||
120
- !isEqual(props.previousMessage, nextProps.previousMessage) ||
121
- !isEqual(props.nextMessage, nextProps.nextMessage)
122
-
123
- if (shouldUpdate)
124
- return false
125
-
126
- return true
127
- })
128
-
129
- export default Message
115
+ export default memo(Message)
@@ -1,9 +1,9 @@
1
1
  import { ViewStyle, LayoutChangeEvent } from 'react-native'
2
2
  import { AvatarProps } from '../Avatar'
3
- import { SystemMessageProps } from '../SystemMessage'
3
+ import { BubbleProps } from '../Bubble'
4
4
  import { DayProps } from '../Day'
5
+ import { SystemMessageProps } from '../SystemMessage'
5
6
  import { IMessage, User, LeftRightStyle } from '../types'
6
- import { BubbleProps } from '../Bubble'
7
7
 
8
8
  export interface MessageProps<TMessage extends IMessage> {
9
9
  showUserAvatar?: boolean
@@ -1,16 +1,28 @@
1
- import React from 'react'
1
+ import React, { useMemo } from 'react'
2
+ import { View, Text, StyleSheet } from 'react-native'
2
3
  import Color from './Color'
3
- import { View, Text } 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 MessageAudio () {
6
- return (
7
- <View style={{ padding: 20 }}>
8
- <Text style={{ color: Color.alizarin, fontWeight: '600' }}>
16
+ const content = useMemo(() => (
17
+ <View style={styles.container}>
18
+ <Text style={styles.text}>
9
19
  {'Audio is not implemented by GiftedChat.'}
10
20
  </Text>
11
- <Text style={{ color: Color.alizarin, fontWeight: '600' }}>
21
+ <Text style={styles.text}>
12
22
  {'\nYou need to provide your own implementation by using renderMessageAudio prop.'}
13
23
  </Text>
14
24
  </View>
15
- )
25
+ ), [])
26
+
27
+ return content
16
28
  }
@@ -2,12 +2,12 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react'
2
2
  import { LayoutChangeEvent } from 'react-native'
3
3
  import Animated, { interpolate, useAnimatedStyle, useDerivedValue, useSharedValue, useAnimatedReaction, withTiming, runOnJS } from 'react-native-reanimated'
4
4
  import { Day } from '../../../Day'
5
+ import stylesCommon from '../../../styles'
5
6
  import { isSameDay } from '../../../utils'
6
7
  import { useAbsoluteScrolledPositionToBottomOfDay, useRelativeScrolledPositionToBottomOfDay } from '../Item'
7
- import { DayAnimatedProps } from './types'
8
8
 
9
- import stylesCommon from '../../../styles'
10
9
  import styles from './styles'
10
+ import { DayAnimatedProps } from './types'
11
11
 
12
12
  export * from './types'
13
13
 
@@ -114,6 +114,19 @@ const DayAnimated = ({ scrolledY, daysPositions, listHeight, renderDay, messages
114
114
  isLoadingEarlierAnim.value = isLoadingEarlier
115
115
  }, [isLoadingEarlierAnim, isLoadingEarlier])
116
116
 
117
+ const dayContent = useMemo(() => {
118
+ if (!createdAt)
119
+ return null
120
+
121
+ return renderDay
122
+ ? renderDay({ ...rest, createdAt })
123
+ : <Day
124
+ {...rest}
125
+ containerStyle={[styles.dayAnimatedDayContainerStyle, rest.containerStyle]}
126
+ createdAt={createdAt}
127
+ />
128
+ }, [createdAt, renderDay, rest])
129
+
117
130
  if (!createdAt)
118
131
  return null
119
132
 
@@ -126,15 +139,7 @@ const DayAnimated = ({ scrolledY, daysPositions, listHeight, renderDay, messages
126
139
  style={contentStyle}
127
140
  pointerEvents='none'
128
141
  >
129
- {
130
- renderDay
131
- ? renderDay({ ...rest, createdAt })
132
- : <Day
133
- {...rest}
134
- containerStyle={[styles.dayAnimatedDayContainerStyle, rest.containerStyle]}
135
- createdAt={createdAt}
136
- />
137
- }
142
+ {dayContent}
138
143
  </Animated.View>
139
144
  </Animated.View>
140
145
  )
@@ -1,11 +1,11 @@
1
1
  import React, { forwardRef, useCallback, useMemo } from 'react'
2
2
  import { LayoutChangeEvent, View } from 'react-native'
3
- import { IMessage } from '../../../types'
4
- import Message, { MessageProps } from '../../../Message'
5
3
  import Animated, { interpolate, useAnimatedStyle, useDerivedValue, useSharedValue } from 'react-native-reanimated'
6
- import { DaysPositions } from '../../types'
7
4
  import { Day } from '../../../Day'
5
+ import Message, { MessageProps } from '../../../Message'
6
+ import { IMessage } from '../../../types'
8
7
  import { isSameDay } from '../../../utils'
8
+ import { DaysPositions } from '../../types'
9
9
  import { ItemProps } from './types'
10
10
 
11
11
  export * from './types'
@@ -33,7 +33,13 @@ export const useRelativeScrolledPositionToBottomOfDay = (
33
33
  const absoluteScrolledPositionToBottomOfDay = useAbsoluteScrolledPositionToBottomOfDay(listHeight, scrolledY, containerHeight, dayBottomMargin, dayTopOffset)
34
34
 
35
35
  // sorted array of days positions by y
36
- const daysPositionsArray = useDerivedValue(() => Object.values(daysPositions.value).sort((a, b) => a.y - b.y))
36
+ const daysPositionsArray = useDerivedValue(() => {
37
+ return Object.values(daysPositions.value).sort((a, b) => {
38
+ 'worklet'
39
+
40
+ return a.y - b.y
41
+ })
42
+ })
37
43
 
38
44
  // find current day position by scrolled position
39
45
  const currentDayPosition = useDerivedValue(() => {
@@ -1,5 +1,5 @@
1
- import { MessageContainerProps, DaysPositions } from '../../types'
2
1
  import { IMessage } from '../../../types'
2
+ import { MessageContainerProps, DaysPositions } from '../../types'
3
3
 
4
4
  export interface ItemProps<TMessage extends IMessage> extends MessageContainerProps<TMessage> {
5
5
  currentMessage: TMessage
@@ -6,28 +6,28 @@ import {
6
6
  Platform,
7
7
  LayoutChangeEvent,
8
8
  ListRenderItemInfo,
9
- FlatList,
10
9
  CellRendererProps,
11
10
  } from 'react-native'
11
+ import { FlatList } from 'react-native-gesture-handler'
12
12
  import Animated, { runOnJS, useAnimatedScrollHandler, useAnimatedStyle, useSharedValue, withTiming } from 'react-native-reanimated'
13
- import { ReanimatedScrollEvent } from 'react-native-reanimated/lib/typescript/hook/commonTypes'
14
- import DayAnimated from './components/DayAnimated'
15
- import Item from './components/Item'
16
-
17
13
  import { LoadEarlier } from '../LoadEarlier'
14
+ import { warning } from '../logging'
15
+ import { ReanimatedScrollEvent } from '../reanimatedCompat'
16
+
17
+ import stylesCommon from '../styles'
18
18
  import { IMessage } from '../types'
19
19
  import TypingIndicator from '../TypingIndicator'
20
- import { MessageContainerProps, DaysPositions } from './types'
21
- import { ItemProps } from './components/Item/types'
20
+ import { isSameDay, useCallbackThrottled } from '../utils'
21
+ import DayAnimated from './components/DayAnimated'
22
22
 
23
- import { warning } from '../logging'
24
- import stylesCommon from '../styles'
23
+ import Item from './components/Item'
24
+ import { ItemProps } from './components/Item/types'
25
25
  import styles from './styles'
26
- import { isSameDay, useCallbackThrottled } from '../utils'
26
+ import { MessageContainerProps, DaysPositions } from './types'
27
27
 
28
28
  export * from './types'
29
29
 
30
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
30
+
31
31
  const AnimatedFlatList = Animated.createAnimatedComponent(FlatList) as React.ComponentType<any>
32
32
 
33
33
  function MessageContainer<TMessage extends IMessage = IMessage> (props: MessageContainerProps<TMessage>) {
@@ -39,9 +39,8 @@ function MessageContainer<TMessage extends IMessage = IMessage> (props: MessageC
39
39
  onLoadEarlier,
40
40
  inverted = true,
41
41
  loadEarlier = false,
42
- listViewProps,
43
- invertibleScrollViewProps,
44
- extraData = null,
42
+ listProps,
43
+ extraData,
45
44
  isScrollToBottomEnabled = false,
46
45
  scrollToBottomOffset = 200,
47
46
  alignTop = false,
@@ -73,8 +72,8 @@ function MessageContainer<TMessage extends IMessage = IMessage> (props: MessageC
73
72
  if (renderTypingIndicatorProp)
74
73
  return renderTypingIndicatorProp()
75
74
 
76
- return <TypingIndicator isTyping={isTyping} />
77
- }, [isTyping, renderTypingIndicatorProp])
75
+ return <TypingIndicator isTyping={isTyping} style={props.typingIndicatorStyle} />
76
+ }, [isTyping, renderTypingIndicatorProp, props.typingIndicatorStyle])
78
77
 
79
78
  const ListFooterComponent = useMemo(() => {
80
79
  if (renderFooterProp)
@@ -151,6 +150,12 @@ function MessageContainer<TMessage extends IMessage = IMessage> (props: MessageC
151
150
  changeScrollToBottomVisibility(false)
152
151
  }, [handleOnScrollProp, inverted, scrollToBottomOffset, changeScrollToBottomVisibility, isScrollingDown, lastScrolledY])
153
152
 
153
+ const restProps = useMemo(() => {
154
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
155
+ const { messages: _, ...rest } = props
156
+ return rest
157
+ }, [props])
158
+
154
159
  const renderItem = useCallback(({ item, index }: ListRenderItemInfo<unknown>): React.ReactElement | null => {
155
160
  const messageItem = item as TMessage
156
161
 
@@ -167,8 +172,6 @@ function MessageContainer<TMessage extends IMessage = IMessage> (props: MessageC
167
172
  messageItem.user = { _id: 0 }
168
173
  }
169
174
 
170
- const { messages, ...restProps } = props
171
-
172
175
  if (messages && user) {
173
176
  const previousMessage =
174
177
  (inverted ? messages[index + 1] : messages[index - 1]) || {}
@@ -192,22 +195,29 @@ function MessageContainer<TMessage extends IMessage = IMessage> (props: MessageC
192
195
  }
193
196
 
194
197
  return null
195
- }, [props, inverted, scrolledY, daysPositions, listHeight, user])
198
+ }, [messages, restProps, inverted, scrolledY, daysPositions, listHeight, user])
199
+
200
+ const emptyContent = useMemo(() => {
201
+ if (!renderChatEmptyProp)
202
+ return null
203
+
204
+ return renderChatEmptyProp()
205
+ }, [renderChatEmptyProp])
196
206
 
197
207
  const renderChatEmpty = useCallback(() => {
198
208
  if (renderChatEmptyProp)
199
209
  return inverted
200
210
  ? (
201
- renderChatEmptyProp()
211
+ emptyContent
202
212
  )
203
213
  : (
204
214
  <View style={[stylesCommon.fill, styles.emptyChatContainer]}>
205
- {renderChatEmptyProp()}
215
+ {emptyContent}
206
216
  </View>
207
217
  )
208
218
 
209
219
  return <View style={stylesCommon.fill} />
210
- }, [inverted, renderChatEmptyProp])
220
+ }, [inverted, renderChatEmptyProp, emptyContent])
211
221
 
212
222
  const ListHeaderComponent = useMemo(() => {
213
223
  const content = renderLoadEarlier()
@@ -227,6 +237,25 @@ function MessageContainer<TMessage extends IMessage = IMessage> (props: MessageC
227
237
  return <Text>{'V'}</Text>
228
238
  }, [scrollToBottomComponentProp])
229
239
 
240
+ const handleScrollToBottomPress = useCallback(() => {
241
+ doScrollToBottom()
242
+ }, [doScrollToBottom])
243
+
244
+ const scrollToBottomContent = useMemo(() => {
245
+ return (
246
+ <Animated.View
247
+ style={[
248
+ stylesCommon.centerItems,
249
+ styles.scrollToBottomContent,
250
+ scrollToBottomStyle,
251
+ scrollToBottomStyleAnim,
252
+ ]}
253
+ >
254
+ {renderScrollBottomComponent()}
255
+ </Animated.View>
256
+ )
257
+ }, [scrollToBottomStyle, scrollToBottomStyleAnim, renderScrollBottomComponent])
258
+
230
259
  const ScrollToBottomWrapper = useCallback(() => {
231
260
  if (!isScrollToBottomEnabled)
232
261
  return null
@@ -237,21 +266,12 @@ function MessageContainer<TMessage extends IMessage = IMessage> (props: MessageC
237
266
  return (
238
267
  <Pressable
239
268
  style={styles.scrollToBottom}
240
- onPress={() => doScrollToBottom()}
269
+ onPress={handleScrollToBottomPress}
241
270
  >
242
- <Animated.View
243
- style={[
244
- stylesCommon.centerItems,
245
- styles.scrollToBottomContent,
246
- scrollToBottomStyle,
247
- scrollToBottomStyleAnim,
248
- ]}
249
- >
250
- {renderScrollBottomComponent()}
251
- </Animated.View>
271
+ {scrollToBottomContent}
252
272
  </Pressable>
253
273
  )
254
- }, [scrollToBottomStyle, renderScrollBottomComponent, doScrollToBottom, scrollToBottomStyleAnim, isScrollToBottomEnabled, isScrollToBottomVisible])
274
+ }, [isScrollToBottomEnabled, isScrollToBottomVisible, handleScrollToBottomPress, scrollToBottomContent])
255
275
 
256
276
  const onLayoutList = useCallback((event: LayoutChangeEvent) => {
257
277
  listHeight.value = event.nativeEvent.layout.height
@@ -265,8 +285,8 @@ function MessageContainer<TMessage extends IMessage = IMessage> (props: MessageC
265
285
  doScrollToBottom(false)
266
286
  }, 500)
267
287
 
268
- listViewProps?.onLayout?.(event)
269
- }, [inverted, messages, doScrollToBottom, listHeight, listViewProps, isScrollToBottomEnabled])
288
+ listProps?.onLayout?.(event)
289
+ }, [inverted, messages, doScrollToBottom, listHeight, listProps, isScrollToBottomEnabled])
270
290
 
271
291
  const onEndReached = useCallback(() => {
272
292
  if (
@@ -378,7 +398,6 @@ function MessageContainer<TMessage extends IMessage = IMessage> (props: MessageC
378
398
  inverted={inverted}
379
399
  automaticallyAdjustContentInsets={false}
380
400
  style={stylesCommon.fill}
381
- {...invertibleScrollViewProps}
382
401
  ListEmptyComponent={renderChatEmpty}
383
402
  ListFooterComponent={
384
403
  inverted ? ListHeaderComponent : ListFooterComponent
@@ -390,7 +409,7 @@ function MessageContainer<TMessage extends IMessage = IMessage> (props: MessageC
390
409
  scrollEventThrottle={1}
391
410
  onEndReached={onEndReached}
392
411
  onEndReachedThreshold={0.1}
393
- {...listViewProps}
412
+ {...listProps}
394
413
  onLayout={onLayoutList}
395
414
  CellRendererComponent={renderCell}
396
415
  />
@@ -3,44 +3,69 @@ import {
3
3
  FlatListProps,
4
4
  StyleProp,
5
5
  ViewStyle,
6
- FlatList,
7
6
  } from 'react-native'
7
+ import { FlatList } from 'react-native-gesture-handler'
8
8
 
9
9
  import { LoadEarlierProps } from '../LoadEarlier'
10
10
  import { MessageProps } from '../Message'
11
+ import { ReanimatedScrollEvent } from '../reanimatedCompat'
11
12
  import { User, IMessage, Reply, DayProps } from '../types'
12
- import { ReanimatedScrollEvent } from 'react-native-reanimated/lib/typescript/hook/commonTypes'
13
+ import { TypingIndicatorProps } from '../TypingIndicator/types'
13
14
 
14
- export type ListViewProps<TMessage extends IMessage = IMessage> = Partial<FlatListProps<TMessage>>
15
+ export type ListProps<TMessage extends IMessage = IMessage> = Partial<FlatListProps<TMessage>>
15
16
 
16
17
  export type AnimatedList<TMessage> = FlatList<TMessage>
17
18
 
18
- export interface MessageContainerProps<TMessage extends IMessage = IMessage> {
19
+ export interface MessageContainerProps<TMessage extends IMessage = IMessage>
20
+ extends Omit<TypingIndicatorProps, 'style'> {
21
+ /** Ref for the FlatList message container */
19
22
  forwardRef?: RefObject<AnimatedList<TMessage>>
23
+ /** Messages to display */
20
24
  messages?: TMessage[]
21
- isTyping?: boolean
25
+ /** User sending the messages: { _id, name, avatar } */
22
26
  user?: User
23
- listViewProps?: ListViewProps
27
+ /** Additional props for FlatList */
28
+ listProps?: ListProps<TMessage>
29
+ /** Reverses display order of messages; default is true */
24
30
  inverted?: boolean
31
+ /** Enables the "Load earlier messages" button */
25
32
  loadEarlier?: boolean
33
+ /** Controls whether or not the message bubbles appear at the top of the chat */
26
34
  alignTop?: boolean
35
+ /** Enables the isScrollToBottomEnabled Component */
27
36
  isScrollToBottomEnabled?: boolean
37
+ /** Scroll to bottom wrapper style */
28
38
  scrollToBottomStyle?: StyleProp<ViewStyle>
29
- invertibleScrollViewProps?: object
39
+ /** This can be used to pass unknown data which needs to be re-rendered */
30
40
  extraData?: object
41
+ /** Distance from bottom before showing scroll to bottom button */
31
42
  scrollToBottomOffset?: number
43
+ /** Custom component to render when messages are empty */
32
44
  renderChatEmpty?(): React.ReactNode
45
+ /** Custom footer component on the ListView, e.g. 'User is typing...' */
33
46
  renderFooter?(props: MessageContainerProps<TMessage>): React.ReactNode
47
+ /** Custom message container */
34
48
  renderMessage?(props: MessageProps<TMessage>): React.ReactElement
49
+ /** Custom day above a message */
35
50
  renderDay?(props: DayProps): React.ReactNode
51
+ /** Custom "Load earlier messages" button */
36
52
  renderLoadEarlier?(props: LoadEarlierProps): React.ReactNode
53
+ /** Custom typing indicator */
37
54
  renderTypingIndicator?(): React.ReactNode
55
+ /** Scroll to bottom custom component */
38
56
  scrollToBottomComponent?(): React.ReactNode
57
+ /** Callback when loading earlier messages */
39
58
  onLoadEarlier?(): void
59
+ /** Callback when quick reply is sent */
40
60
  onQuickReply?(replies: Reply[]): void
61
+ /** Infinite scroll up when reach the top of messages container, automatically call onLoadEarlier function if exist */
41
62
  infiniteScroll?: boolean
63
+ /** Display an ActivityIndicator when loading earlier messages */
42
64
  isLoadingEarlier?: boolean
65
+ /** Custom scroll event handler */
43
66
  handleOnScroll?(event: ReanimatedScrollEvent): void
67
+ /** Style for TypingIndicator component */
68
+ typingIndicatorStyle?: StyleProp<ViewStyle>
44
69
  }
45
70
 
46
71
  export interface State {