react-native-gifted-chat 2.6.5 → 2.7.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 (228) hide show
  1. package/README.md +7 -16
  2. package/lib/Actions.d.ts +0 -11
  3. package/lib/Actions.js +2 -14
  4. package/lib/Actions.js.map +1 -1
  5. package/lib/Avatar.d.ts +1 -23
  6. package/lib/Avatar.js +32 -40
  7. package/lib/Avatar.js.map +1 -1
  8. package/lib/Bubble/index.d.ts +30 -0
  9. package/lib/{Bubble.js → Bubble/index.js} +31 -181
  10. package/lib/Bubble/index.js.map +1 -0
  11. package/lib/Bubble/styles.d.ts +69 -0
  12. package/lib/Bubble/styles.js +72 -0
  13. package/lib/Bubble/styles.js.map +1 -0
  14. package/lib/Bubble/types.d.ts +47 -0
  15. package/lib/Bubble/types.js +2 -0
  16. package/lib/Bubble/types.js.map +1 -0
  17. package/lib/Composer.d.ts +0 -17
  18. package/lib/Composer.js +3 -18
  19. package/lib/Composer.js.map +1 -1
  20. package/lib/Constant.d.ts +1 -1
  21. package/lib/Constant.js +1 -1
  22. package/lib/Constant.js.map +1 -1
  23. package/lib/Day/index.d.ts +4 -0
  24. package/lib/Day/index.js +39 -0
  25. package/lib/Day/index.js.map +1 -0
  26. package/lib/Day/styles.d.ts +20 -0
  27. package/lib/Day/styles.js +22 -0
  28. package/lib/Day/styles.js.map +1 -0
  29. package/lib/Day/types.d.ts +9 -0
  30. package/lib/Day/types.js +2 -0
  31. package/lib/Day/types.js.map +1 -0
  32. package/lib/GiftedAvatar.d.ts +1 -11
  33. package/lib/GiftedAvatar.js +26 -33
  34. package/lib/GiftedAvatar.js.map +1 -1
  35. package/lib/GiftedChat/index.d.ts +26 -0
  36. package/lib/{GiftedChat.js → GiftedChat/index.js} +47 -52
  37. package/lib/GiftedChat/index.js.map +1 -0
  38. package/lib/GiftedChat/styles.d.ts +6 -0
  39. package/lib/GiftedChat/styles.js +7 -0
  40. package/lib/GiftedChat/styles.js.map +1 -0
  41. package/lib/{GiftedChat.d.ts → GiftedChat/types.d.ts} +27 -37
  42. package/lib/GiftedChat/types.js +2 -0
  43. package/lib/GiftedChat/types.js.map +1 -0
  44. package/lib/InputToolbar.d.ts +1 -14
  45. package/lib/InputToolbar.js +0 -12
  46. package/lib/InputToolbar.js.map +1 -1
  47. package/lib/LoadEarlier.d.ts +0 -14
  48. package/lib/LoadEarlier.js +2 -16
  49. package/lib/LoadEarlier.js.map +1 -1
  50. package/lib/Message/index.d.ts +6 -0
  51. package/lib/Message/index.js +85 -0
  52. package/lib/Message/index.js.map +1 -0
  53. package/lib/Message/styles.d.ts +21 -0
  54. package/lib/Message/styles.js +22 -0
  55. package/lib/Message/styles.js.map +1 -0
  56. package/lib/Message/types.d.ts +22 -0
  57. package/lib/Message/types.js +2 -0
  58. package/lib/Message/types.js.map +1 -0
  59. package/lib/MessageAudio.js +1 -2
  60. package/lib/MessageAudio.js.map +1 -1
  61. package/lib/MessageContainer/components/DayAnimated/index.d.ts +5 -0
  62. package/lib/MessageContainer/components/DayAnimated/index.js +85 -0
  63. package/lib/MessageContainer/components/DayAnimated/index.js.map +1 -0
  64. package/lib/MessageContainer/components/DayAnimated/styles.d.ts +11 -0
  65. package/lib/MessageContainer/components/DayAnimated/styles.js +12 -0
  66. package/lib/MessageContainer/components/DayAnimated/styles.js.map +1 -0
  67. package/lib/MessageContainer/components/DayAnimated/types.d.ts +17 -0
  68. package/lib/MessageContainer/components/DayAnimated/types.js +2 -0
  69. package/lib/MessageContainer/components/DayAnimated/types.js.map +1 -0
  70. package/lib/MessageContainer/components/Item/index.d.ts +22 -0
  71. package/lib/MessageContainer/components/Item/index.js +69 -0
  72. package/lib/MessageContainer/components/Item/index.js.map +1 -0
  73. package/lib/MessageContainer/components/Item/types.d.ts +18 -0
  74. package/lib/MessageContainer/components/Item/types.js +2 -0
  75. package/lib/MessageContainer/components/Item/types.js.map +1 -0
  76. package/lib/MessageContainer/index.d.ts +6 -0
  77. package/lib/MessageContainer/index.js +175 -0
  78. package/lib/MessageContainer/index.js.map +1 -0
  79. package/lib/MessageContainer/styles.d.ts +34 -0
  80. package/lib/MessageContainer/styles.js +31 -0
  81. package/lib/MessageContainer/styles.js.map +1 -0
  82. package/lib/MessageContainer/types.d.ts +54 -0
  83. package/lib/MessageContainer/types.js +2 -0
  84. package/lib/MessageContainer/types.js.map +1 -0
  85. package/lib/MessageImage.d.ts +1 -12
  86. package/lib/MessageImage.js +2 -12
  87. package/lib/MessageImage.js.map +1 -1
  88. package/lib/MessageText.d.ts +1 -24
  89. package/lib/MessageText.js +0 -22
  90. package/lib/MessageText.js.map +1 -1
  91. package/lib/MessageVideo.js +1 -2
  92. package/lib/MessageVideo.js.map +1 -1
  93. package/lib/QuickReplies.d.ts +1 -12
  94. package/lib/QuickReplies.js +10 -20
  95. package/lib/QuickReplies.js.map +1 -1
  96. package/lib/Send.d.ts +2 -16
  97. package/lib/Send.js +0 -13
  98. package/lib/Send.js.map +1 -1
  99. package/lib/SystemMessage.d.ts +1 -10
  100. package/lib/SystemMessage.js +2 -12
  101. package/lib/SystemMessage.js.map +1 -1
  102. package/lib/Time.d.ts +1 -17
  103. package/lib/Time.js +0 -15
  104. package/lib/Time.js.map +1 -1
  105. package/lib/TypingIndicator/index.d.ts +5 -0
  106. package/lib/{TypingIndicator.js → TypingIndicator/index.js} +9 -30
  107. package/lib/TypingIndicator/index.js.map +1 -0
  108. package/lib/TypingIndicator/styles.d.ts +20 -0
  109. package/lib/TypingIndicator/styles.js +22 -0
  110. package/lib/TypingIndicator/styles.js.map +1 -0
  111. package/lib/TypingIndicator/types.d.ts +3 -0
  112. package/lib/TypingIndicator/types.js +2 -0
  113. package/lib/TypingIndicator/types.js.map +1 -0
  114. package/lib/index.d.ts +0 -1
  115. package/lib/index.js +0 -1
  116. package/lib/index.js.map +1 -1
  117. package/lib/styles.d.ts +10 -0
  118. package/lib/styles.js +11 -0
  119. package/lib/styles.js.map +1 -0
  120. package/lib/{Models.d.ts → types.d.ts} +1 -1
  121. package/lib/types.js +2 -0
  122. package/lib/types.js.map +1 -0
  123. package/lib/utils.d.ts +1 -3
  124. package/lib/utils.js +0 -7
  125. package/lib/utils.js.map +1 -1
  126. package/package.json +21 -29
  127. package/src/Actions.tsx +3 -15
  128. package/src/Avatar.tsx +43 -52
  129. package/src/{Bubble.tsx → Bubble/index.tsx} +52 -269
  130. package/src/Bubble/styles.ts +73 -0
  131. package/src/Bubble/types.ts +90 -0
  132. package/src/Composer.tsx +3 -19
  133. package/src/Constant.ts +1 -1
  134. package/src/Day/index.tsx +63 -0
  135. package/src/Day/styles.ts +22 -0
  136. package/src/Day/types.ts +14 -0
  137. package/src/GiftedAvatar.tsx +31 -38
  138. package/src/GiftedChat/index.tsx +503 -0
  139. package/src/GiftedChat/styles.ts +7 -0
  140. package/src/GiftedChat/types.ts +206 -0
  141. package/src/InputToolbar.tsx +1 -14
  142. package/src/LoadEarlier.tsx +2 -17
  143. package/src/Message/index.tsx +135 -0
  144. package/src/Message/styles.ts +22 -0
  145. package/src/Message/types.ts +26 -0
  146. package/src/MessageAudio.tsx +1 -4
  147. package/src/MessageContainer/components/DayAnimated/index.tsx +143 -0
  148. package/src/MessageContainer/components/DayAnimated/styles.ts +12 -0
  149. package/src/MessageContainer/components/DayAnimated/types.ts +12 -0
  150. package/src/MessageContainer/components/Item/index.tsx +136 -0
  151. package/src/MessageContainer/components/Item/types.ts +13 -0
  152. package/src/MessageContainer/index.tsx +316 -0
  153. package/src/MessageContainer/styles.ts +31 -0
  154. package/src/MessageContainer/types.ts +60 -0
  155. package/src/MessageImage.tsx +3 -14
  156. package/src/MessageText.tsx +1 -24
  157. package/src/MessageVideo.tsx +1 -4
  158. package/src/QuickReplies.tsx +14 -25
  159. package/src/Send.tsx +1 -15
  160. package/src/SystemMessage.tsx +3 -14
  161. package/src/Time.tsx +1 -17
  162. package/src/{TypingIndicator.tsx → TypingIndicator/index.tsx} +12 -35
  163. package/src/TypingIndicator/styles.ts +22 -0
  164. package/src/TypingIndicator/types.ts +3 -0
  165. package/src/__tests__/Bubble.test.tsx +7 -4
  166. package/src/__tests__/GiftedAvatar.test.tsx +6 -2
  167. package/src/__tests__/GiftedChat.test.tsx +20 -14
  168. package/src/__tests__/Message.test.tsx +4 -1
  169. package/src/__tests__/__snapshots__/Actions.test.tsx.snap +6 -2
  170. package/src/__tests__/__snapshots__/Bubble.test.tsx.snap +3 -1
  171. package/src/__tests__/__snapshots__/Composer.test.tsx.snap +2 -0
  172. package/src/__tests__/__snapshots__/Constant.test.tsx.snap +1 -1
  173. package/src/__tests__/__snapshots__/Day.test.tsx.snap +1 -33
  174. package/src/__tests__/__snapshots__/GiftedAvatar.test.tsx.snap +4 -2
  175. package/src/__tests__/__snapshots__/GiftedChat.test.tsx.snap +22 -9
  176. package/src/__tests__/__snapshots__/InputToolbar.test.tsx.snap +2 -0
  177. package/src/__tests__/__snapshots__/LoadEarlier.test.tsx.snap +3 -1
  178. package/src/__tests__/__snapshots__/Message.test.tsx.snap +21 -100
  179. package/src/__tests__/__snapshots__/MessageContainer.test.tsx.snap +282 -82
  180. package/src/__tests__/__snapshots__/MessageImage.test.tsx.snap +8 -4
  181. package/src/__tests__/__snapshots__/SystemMessage.test.tsx.snap +5 -1
  182. package/src/__tests__/data.ts +1 -1
  183. package/src/index.ts +0 -2
  184. package/src/styles.ts +11 -0
  185. package/src/{Models.ts → types.ts} +1 -1
  186. package/src/utils.ts +1 -9
  187. package/lib/Actions.js.flow +0 -21
  188. package/lib/Avatar.js.flow +0 -27
  189. package/lib/Bubble.d.ts +0 -148
  190. package/lib/Bubble.js.flow +0 -69
  191. package/lib/Bubble.js.map +0 -1
  192. package/lib/Composer.js.flow +0 -24
  193. package/lib/Day.d.ts +0 -15
  194. package/lib/Day.js +0 -36
  195. package/lib/Day.js.flow +0 -23
  196. package/lib/Day.js.map +0 -1
  197. package/lib/GiftedAvatar.js.flow +0 -17
  198. package/lib/GiftedChat.js.flow +0 -163
  199. package/lib/GiftedChat.js.map +0 -1
  200. package/lib/InputToolbar.js.flow +0 -31
  201. package/lib/LoadEarlier.js.flow +0 -20
  202. package/lib/Message.d.ts +0 -67
  203. package/lib/Message.js +0 -157
  204. package/lib/Message.js.flow +0 -32
  205. package/lib/Message.js.map +0 -1
  206. package/lib/MessageAudio.js.flow +0 -15
  207. package/lib/MessageContainer.d.ts +0 -105
  208. package/lib/MessageContainer.js +0 -224
  209. package/lib/MessageContainer.js.flow +0 -39
  210. package/lib/MessageContainer.js.map +0 -1
  211. package/lib/MessageImage.js.flow +0 -20
  212. package/lib/MessageText.js.flow +0 -23
  213. package/lib/MessageVideo.js.flow +0 -16
  214. package/lib/Models.js +0 -2
  215. package/lib/Models.js.map +0 -1
  216. package/lib/QuickReplies.js.flow +0 -25
  217. package/lib/Send.js.flow +0 -19
  218. package/lib/SystemMessage.js.flow +0 -18
  219. package/lib/Time.js.flow +0 -19
  220. package/lib/TypingIndicator.d.ts +0 -6
  221. package/lib/TypingIndicator.js.map +0 -1
  222. package/lib/index.js.flow +0 -2
  223. package/lib/types.js.flow +0 -43
  224. package/lib/utils.js.flow +0 -16
  225. package/src/Day.tsx +0 -71
  226. package/src/GiftedChat.tsx +0 -689
  227. package/src/Message.tsx +0 -229
  228. package/src/MessageContainer.tsx +0 -361
package/src/Message.tsx DELETED
@@ -1,229 +0,0 @@
1
- import PropTypes from 'prop-types'
2
- import React from 'react'
3
- import { View, StyleSheet, ViewStyle, LayoutChangeEvent } from 'react-native'
4
- import isEqual from 'lodash.isequal'
5
-
6
- import { Avatar, AvatarProps } from './Avatar'
7
- import Bubble from './Bubble'
8
- import { SystemMessage, SystemMessageProps } from './SystemMessage'
9
- import { Day, DayProps } from './Day'
10
-
11
- import { StylePropType, isSameUser } from './utils'
12
- import { IMessage, User, LeftRightStyle } from './Models'
13
-
14
- const styles = {
15
- left: StyleSheet.create({
16
- container: {
17
- flexDirection: 'row',
18
- alignItems: 'flex-end',
19
- justifyContent: 'flex-start',
20
- marginLeft: 8,
21
- marginRight: 0,
22
- },
23
- }),
24
- right: StyleSheet.create({
25
- container: {
26
- flexDirection: 'row',
27
- alignItems: 'flex-end',
28
- justifyContent: 'flex-end',
29
- marginLeft: 0,
30
- marginRight: 8,
31
- },
32
- }),
33
- }
34
-
35
- export interface MessageProps<TMessage extends IMessage> {
36
- showUserAvatar?: boolean
37
- position: 'left' | 'right'
38
- currentMessage: TMessage
39
- nextMessage?: TMessage
40
- previousMessage?: TMessage
41
- user: User
42
- inverted?: boolean
43
- containerStyle?: LeftRightStyle<ViewStyle>
44
- renderBubble?(props: Bubble['props']): React.ReactNode
45
- renderDay?(props: DayProps<TMessage>): React.ReactNode
46
- renderSystemMessage?(props: SystemMessageProps<TMessage>): React.ReactNode
47
- renderAvatar?(props: AvatarProps<TMessage>): React.ReactNode
48
- shouldUpdateMessage?(
49
- props: MessageProps<IMessage>,
50
- nextProps: MessageProps<IMessage>,
51
- ): boolean
52
- onMessageLayout?(event: LayoutChangeEvent): void
53
- }
54
-
55
- export default class Message<
56
- TMessage extends IMessage = IMessage,
57
- > extends React.Component<MessageProps<TMessage>> {
58
- static defaultProps = {
59
- renderAvatar: undefined,
60
- renderBubble: null,
61
- renderDay: null,
62
- renderSystemMessage: null,
63
- position: 'left',
64
- currentMessage: {},
65
- nextMessage: {},
66
- previousMessage: {},
67
- user: {},
68
- containerStyle: {},
69
- showUserAvatar: false,
70
- inverted: true,
71
- shouldUpdateMessage: undefined,
72
- onMessageLayout: undefined,
73
- }
74
-
75
- static propTypes = {
76
- renderAvatar: PropTypes.func,
77
- showUserAvatar: PropTypes.bool,
78
- renderBubble: PropTypes.func,
79
- renderDay: PropTypes.func,
80
- renderSystemMessage: PropTypes.func,
81
- position: PropTypes.oneOf(['left', 'right']),
82
- currentMessage: PropTypes.object,
83
- nextMessage: PropTypes.object,
84
- previousMessage: PropTypes.object,
85
- user: PropTypes.object,
86
- inverted: PropTypes.bool,
87
- containerStyle: PropTypes.shape({
88
- left: StylePropType,
89
- right: StylePropType,
90
- }),
91
- shouldUpdateMessage: PropTypes.func,
92
- onMessageLayout: PropTypes.func,
93
- }
94
-
95
- shouldComponentUpdate (nextProps: MessageProps<TMessage>) {
96
- const next = nextProps.currentMessage!
97
- const current = this.props.currentMessage!
98
- const { previousMessage, nextMessage } = this.props
99
- const nextPropsMessage = nextProps.nextMessage
100
- const nextPropsPreviousMessage = nextProps.previousMessage
101
-
102
- let shouldUpdate =
103
- this.props.shouldUpdateMessage?.(this.props, nextProps) || false
104
-
105
- shouldUpdate =
106
- shouldUpdate ||
107
- !isEqual(current, next) ||
108
- !isEqual(previousMessage, nextPropsPreviousMessage) ||
109
- !isEqual(nextMessage, nextPropsMessage)
110
-
111
- return shouldUpdate
112
- }
113
-
114
- renderDay () {
115
- if (this.props.currentMessage && this.props.currentMessage.createdAt) {
116
- const {
117
- /* eslint-disable @typescript-eslint/no-unused-vars */
118
- containerStyle,
119
- onMessageLayout,
120
- /* eslint-enable @typescript-eslint/no-unused-vars */
121
- ...props
122
- } = this.props
123
-
124
- if (this.props.renderDay)
125
- return this.props.renderDay(props)
126
-
127
- return <Day {...props} />
128
- }
129
- return null
130
- }
131
-
132
- renderBubble () {
133
- const {
134
- /* eslint-disable @typescript-eslint/no-unused-vars */
135
- containerStyle,
136
- onMessageLayout,
137
- /* eslint-enable @typescript-eslint/no-unused-vars */
138
- ...props
139
- } = this.props
140
-
141
- if (this.props.renderBubble)
142
- return this.props.renderBubble(props)
143
-
144
- return <Bubble {...props} />
145
- }
146
-
147
- renderSystemMessage () {
148
- const {
149
- /* eslint-disable @typescript-eslint/no-unused-vars */
150
- containerStyle,
151
- onMessageLayout,
152
- /* eslint-enable @typescript-eslint/no-unused-vars */
153
- ...props
154
- } = this.props
155
-
156
- if (this.props.renderSystemMessage)
157
- return this.props.renderSystemMessage(props)
158
-
159
- return <SystemMessage {...props} />
160
- }
161
-
162
- renderAvatar () {
163
- const { user, currentMessage, showUserAvatar } = this.props
164
-
165
- if (
166
- user &&
167
- user._id &&
168
- currentMessage &&
169
- currentMessage.user &&
170
- user._id === currentMessage.user._id &&
171
- !showUserAvatar
172
- )
173
- return null
174
-
175
- if (
176
- currentMessage &&
177
- currentMessage.user &&
178
- currentMessage.user.avatar === null
179
- )
180
- return null
181
-
182
- const {
183
- /* eslint-disable @typescript-eslint/no-unused-vars */
184
- containerStyle,
185
- onMessageLayout,
186
- /* eslint-enable @typescript-eslint/no-unused-vars */
187
- ...props
188
- } = this.props
189
-
190
- return <Avatar {...props} />
191
- }
192
-
193
- render () {
194
- const {
195
- currentMessage,
196
- onMessageLayout,
197
- nextMessage,
198
- position,
199
- containerStyle,
200
- } = this.props
201
- if (currentMessage) {
202
- const sameUser = isSameUser(currentMessage, nextMessage!)
203
- return (
204
- <View onLayout={onMessageLayout}>
205
- {this.renderDay()}
206
- {currentMessage.system
207
- ? (
208
- this.renderSystemMessage()
209
- )
210
- : (
211
- <View
212
- style={[
213
- styles[position].container,
214
- { marginBottom: sameUser ? 2 : 10 },
215
- !this.props.inverted && { marginBottom: 2 },
216
- containerStyle && containerStyle[position],
217
- ]}
218
- >
219
- {this.props.position === 'left' ? this.renderAvatar() : null}
220
- {this.renderBubble()}
221
- {this.props.position === 'right' ? this.renderAvatar() : null}
222
- </View>
223
- )}
224
- </View>
225
- )
226
- }
227
- return null
228
- }
229
- }
@@ -1,361 +0,0 @@
1
- import React, { RefObject } from 'react'
2
- import PropTypes from 'prop-types'
3
-
4
- import {
5
- FlatList,
6
- View,
7
- StyleSheet,
8
- TouchableOpacity,
9
- Text,
10
- ListRenderItemInfo,
11
- NativeSyntheticEvent,
12
- NativeScrollEvent,
13
- StyleProp,
14
- ViewStyle,
15
- Platform,
16
- } from 'react-native'
17
-
18
- import { LoadEarlier, LoadEarlierProps } from './LoadEarlier'
19
- import Message from './Message'
20
- import Color from './Color'
21
- import { User, IMessage, Reply } from './Models'
22
- import TypingIndicator from './TypingIndicator'
23
-
24
- import { StylePropType } from './utils'
25
- import { warning } from './logging'
26
-
27
- const styles = StyleSheet.create({
28
- container: {
29
- flex: 1,
30
- },
31
- containerAlignTop: {
32
- flexDirection: 'row',
33
- alignItems: 'flex-start',
34
- },
35
- contentContainerStyle: {
36
- flexGrow: 1,
37
- justifyContent: 'flex-start',
38
- },
39
- emptyChatContainer: {
40
- flex: 1,
41
- transform: [{ scaleY: -1 }],
42
- },
43
- headerWrapper: {
44
- flex: 1,
45
- },
46
- listStyle: {
47
- flex: 1,
48
- },
49
- scrollToBottomStyle: {
50
- opacity: 0.8,
51
- position: 'absolute',
52
- right: 10,
53
- bottom: 30,
54
- zIndex: 999,
55
- height: 40,
56
- width: 40,
57
- borderRadius: 20,
58
- backgroundColor: Color.white,
59
- alignItems: 'center',
60
- justifyContent: 'center',
61
- shadowColor: Color.black,
62
- shadowOpacity: 0.5,
63
- shadowOffset: { width: 0, height: 0 },
64
- shadowRadius: 1,
65
- },
66
- })
67
-
68
- export interface MessageContainerProps<TMessage extends IMessage> {
69
- messages?: TMessage[]
70
- isTyping?: boolean
71
- user?: User
72
- listViewProps: object
73
- inverted?: boolean
74
- loadEarlier?: boolean
75
- alignTop?: boolean
76
- scrollToBottom?: boolean
77
- scrollToBottomStyle?: StyleProp<ViewStyle>
78
- invertibleScrollViewProps?: object
79
- extraData?: object
80
- scrollToBottomOffset?: number
81
- forwardRef?: RefObject<FlatList<TMessage>>
82
- renderChatEmpty?(): React.ReactNode
83
- renderFooter?(props: MessageContainerProps<TMessage>): React.ReactNode
84
- renderMessage?(props: Message['props']): React.ReactElement
85
- renderLoadEarlier?(props: LoadEarlierProps): React.ReactNode
86
- renderTypingIndicator?(): React.ReactNode
87
- scrollToBottomComponent?(): React.ReactNode
88
- onLoadEarlier?(): void
89
- onQuickReply?(replies: Reply[]): void
90
- infiniteScroll?: boolean
91
- isLoadingEarlier?: boolean
92
- handleOnScroll?(event: NativeSyntheticEvent<NativeScrollEvent>): void
93
- }
94
-
95
- interface State {
96
- showScrollBottom: boolean
97
- hasScrolled: boolean
98
- }
99
-
100
- export default class MessageContainer<
101
- TMessage extends IMessage = IMessage,
102
- > extends React.PureComponent<MessageContainerProps<TMessage>, State> {
103
- static defaultProps = {
104
- messages: [],
105
- user: {},
106
- isTyping: false,
107
- renderChatEmpty: null,
108
- renderFooter: null,
109
- renderMessage: null,
110
- onLoadEarlier: () => {},
111
- onQuickReply: () => {},
112
- inverted: true,
113
- loadEarlier: false,
114
- listViewProps: {},
115
- invertibleScrollViewProps: {},
116
- extraData: null,
117
- scrollToBottom: false,
118
- scrollToBottomOffset: 200,
119
- alignTop: false,
120
- scrollToBottomStyle: {},
121
- infiniteScroll: false,
122
- isLoadingEarlier: false,
123
- }
124
-
125
- static propTypes = {
126
- messages: PropTypes.arrayOf(PropTypes.object),
127
- isTyping: PropTypes.bool,
128
- user: PropTypes.object,
129
- renderChatEmpty: PropTypes.func,
130
- renderFooter: PropTypes.func,
131
- renderMessage: PropTypes.func,
132
- renderLoadEarlier: PropTypes.func,
133
- onLoadEarlier: PropTypes.func,
134
- listViewProps: PropTypes.object,
135
- inverted: PropTypes.bool,
136
- loadEarlier: PropTypes.bool,
137
- invertibleScrollViewProps: PropTypes.object,
138
- extraData: PropTypes.object,
139
- scrollToBottom: PropTypes.bool,
140
- scrollToBottomOffset: PropTypes.number,
141
- scrollToBottomComponent: PropTypes.func,
142
- alignTop: PropTypes.bool,
143
- scrollToBottomStyle: StylePropType,
144
- infiniteScroll: PropTypes.bool,
145
- }
146
-
147
- state = {
148
- showScrollBottom: false,
149
- hasScrolled: false,
150
- }
151
-
152
- renderTypingIndicator = () => {
153
- if (this.props.renderTypingIndicator)
154
- return this.props.renderTypingIndicator()
155
- return <TypingIndicator isTyping={this.props.isTyping || false} />
156
- }
157
-
158
- renderFooter = () => {
159
- if (this.props.renderFooter)
160
- return this.props.renderFooter(this.props)
161
-
162
- return this.renderTypingIndicator()
163
- }
164
-
165
- renderLoadEarlier = (props: LoadEarlierProps) => {
166
- if (this.props.loadEarlier === true) {
167
- if (this.props.renderLoadEarlier)
168
- return this.props.renderLoadEarlier(props)
169
-
170
- return <LoadEarlier {...props} />
171
- }
172
- return null
173
- }
174
-
175
- scrollTo (options: { animated?: boolean, offset: number }) {
176
- if (this.props.forwardRef?.current && options)
177
- this.props.forwardRef.current.scrollToOffset(options)
178
- }
179
-
180
- scrollToBottom = (animated: boolean = true) => {
181
- const { inverted } = this.props
182
- if (inverted)
183
- this.scrollTo({ offset: 0, animated })
184
- else if (this.props.forwardRef?.current)
185
- this.props.forwardRef.current.scrollToEnd({ animated })
186
- }
187
-
188
- handleOnScroll = (event: NativeSyntheticEvent<NativeScrollEvent>) => {
189
- this.props.handleOnScroll?.(event)
190
- const {
191
- nativeEvent: {
192
- contentOffset: { y: contentOffsetY },
193
- contentSize: { height: contentSizeHeight },
194
- layoutMeasurement: { height: layoutMeasurementHeight },
195
- },
196
- } = event
197
- const { scrollToBottomOffset } = this.props
198
- if (this.props.inverted)
199
- if (contentOffsetY > scrollToBottomOffset!)
200
- this.setState({ showScrollBottom: true, hasScrolled: true })
201
- else
202
- this.setState({ showScrollBottom: false, hasScrolled: true })
203
- else if (
204
- contentOffsetY < scrollToBottomOffset! &&
205
- contentSizeHeight - layoutMeasurementHeight > scrollToBottomOffset!
206
- )
207
- this.setState({ showScrollBottom: true, hasScrolled: true })
208
- else
209
- this.setState({ showScrollBottom: false, hasScrolled: true })
210
- }
211
-
212
- renderRow = ({ item, index }: ListRenderItemInfo<TMessage>): React.ReactElement | null => {
213
- if (!item._id && item._id !== 0)
214
- warning('GiftedChat: `_id` is missing for message', JSON.stringify(item))
215
-
216
- if (!item.user) {
217
- if (!item.system)
218
- warning(
219
- 'GiftedChat: `user` is missing for message',
220
- JSON.stringify(item)
221
- )
222
-
223
- item.user = { _id: 0 }
224
- }
225
- const { messages, user, inverted, ...restProps } = this.props
226
- if (messages && user) {
227
- const previousMessage =
228
- (inverted ? messages[index + 1] : messages[index - 1]) || {}
229
- const nextMessage =
230
- (inverted ? messages[index - 1] : messages[index + 1]) || {}
231
-
232
- const messageProps: Message['props'] = {
233
- ...restProps,
234
- user,
235
- currentMessage: item,
236
- previousMessage,
237
- inverted,
238
- nextMessage,
239
- position: item.user._id === user._id ? 'right' : 'left',
240
- }
241
-
242
- if (this.props.renderMessage)
243
- return this.props.renderMessage(messageProps)
244
-
245
- return <Message key={item._id.toString()} {...messageProps} />
246
- }
247
- return null
248
- }
249
-
250
- renderChatEmpty = () => {
251
- if (this.props.renderChatEmpty)
252
- return this.props.inverted
253
- ? (
254
- this.props.renderChatEmpty()
255
- )
256
- : (
257
- <View style={styles.emptyChatContainer}>
258
- {this.props.renderChatEmpty()}
259
- </View>
260
- )
261
-
262
- return <View style={styles.container} />
263
- }
264
-
265
- renderHeaderWrapper = () => (
266
- <View style={styles.headerWrapper}>{this.renderLoadEarlier({ ...this.props })}</View>
267
- )
268
-
269
- renderScrollBottomComponent () {
270
- const { scrollToBottomComponent } = this.props
271
-
272
- if (scrollToBottomComponent)
273
- return scrollToBottomComponent()
274
-
275
- return <Text>{'V'}</Text>
276
- }
277
-
278
- renderScrollToBottomWrapper () {
279
- const propsStyle = this.props.scrollToBottomStyle || {}
280
- return (
281
- <View style={[styles.scrollToBottomStyle, propsStyle]}>
282
- <TouchableOpacity
283
- onPress={() => this.scrollToBottom()}
284
- hitSlop={{ top: 5, left: 5, right: 5, bottom: 5 }}
285
- >
286
- {this.renderScrollBottomComponent()}
287
- </TouchableOpacity>
288
- </View>
289
- )
290
- }
291
-
292
- onLayoutList = () => {
293
- if (
294
- !this.props.inverted &&
295
- !!this.props.messages &&
296
- this.props.messages!.length
297
- )
298
- setTimeout(
299
- () => this.scrollToBottom && this.scrollToBottom(false),
300
- 15 * this.props.messages!.length
301
- )
302
- }
303
-
304
- onEndReached = ({ distanceFromEnd }: { distanceFromEnd: number }) => {
305
- const { loadEarlier, onLoadEarlier, infiniteScroll, isLoadingEarlier } =
306
- this.props
307
- if (
308
- infiniteScroll &&
309
- (this.state.hasScrolled || distanceFromEnd > 0) &&
310
- distanceFromEnd <= 100 &&
311
- loadEarlier &&
312
- onLoadEarlier &&
313
- !isLoadingEarlier &&
314
- Platform.OS !== 'web'
315
- )
316
- onLoadEarlier()
317
- }
318
-
319
- keyExtractor = (item: TMessage) => `${item._id}`
320
-
321
- render () {
322
- const { inverted } = this.props
323
-
324
- return (
325
- <View
326
- style={
327
- this.props.alignTop ? styles.containerAlignTop : styles.container
328
- }
329
- >
330
- <FlatList
331
- ref={this.props.forwardRef}
332
- extraData={[this.props.extraData, this.props.isTyping]}
333
- keyExtractor={this.keyExtractor}
334
- automaticallyAdjustContentInsets={false}
335
- inverted={inverted}
336
- data={this.props.messages}
337
- style={styles.listStyle}
338
- contentContainerStyle={styles.contentContainerStyle}
339
- renderItem={this.renderRow}
340
- {...this.props.invertibleScrollViewProps}
341
- ListEmptyComponent={this.renderChatEmpty}
342
- ListFooterComponent={
343
- inverted ? this.renderHeaderWrapper : this.renderFooter
344
- }
345
- ListHeaderComponent={
346
- inverted ? this.renderFooter : this.renderHeaderWrapper
347
- }
348
- onScroll={this.handleOnScroll}
349
- scrollEventThrottle={100}
350
- onLayout={this.onLayoutList}
351
- onEndReached={this.onEndReached}
352
- onEndReachedThreshold={0.1}
353
- {...this.props.listViewProps}
354
- />
355
- {this.state.showScrollBottom && this.props.scrollToBottom
356
- ? this.renderScrollToBottomWrapper()
357
- : null}
358
- </View>
359
- )
360
- }
361
- }