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
@@ -0,0 +1,206 @@
1
+ import React, { RefObject } from 'react'
2
+ import {
3
+ ActionSheetOptions,
4
+ } from '@expo/react-native-action-sheet'
5
+ import {
6
+ TextInput,
7
+ StyleProp,
8
+ TextStyle,
9
+ ViewStyle,
10
+ } from 'react-native'
11
+ import { LightboxProps } from 'react-native-lightbox-v2'
12
+ import { ActionsProps } from '../Actions'
13
+ import { AvatarProps } from '../Avatar'
14
+ import { ComposerProps } from '../Composer'
15
+ import { DayProps } from '../Day'
16
+ import { InputToolbarProps } from '../InputToolbar'
17
+ import { LoadEarlierProps } from '../LoadEarlier'
18
+ import { MessageProps } from '../Message'
19
+ import { MessageImageProps } from '../MessageImage'
20
+ import { MessageTextProps } from '../MessageText'
21
+ import {
22
+ IMessage,
23
+ LeftRightStyle,
24
+ MessageAudioProps,
25
+ MessageVideoProps,
26
+ Reply,
27
+ User,
28
+ } from '../types'
29
+ import { QuickRepliesProps } from '../QuickReplies'
30
+ import { SendProps } from '../Send'
31
+ import { SystemMessageProps } from '../SystemMessage'
32
+ import { TimeProps } from '../Time'
33
+ import MessageContainer, { AnimatedList, ListViewProps } from '../MessageContainer'
34
+ import Bubble from '../Bubble'
35
+
36
+ export interface GiftedChatProps<TMessage extends IMessage = IMessage> extends Partial<Omit<typeof MessageContainer<TMessage>, 'scrollToBottom'>> {
37
+ /* Message container ref */
38
+ messageContainerRef?: RefObject<AnimatedList>
39
+ /* text input ref */
40
+ textInputRef?: RefObject<TextInput>
41
+ /* Messages to display */
42
+ messages?: TMessage[]
43
+ /* Typing Indicator state */
44
+ isTyping?: boolean
45
+ /* Controls whether or not to show user.name property in the message bubble */
46
+ renderUsernameOnMessage?: boolean
47
+ /* Messages container style */
48
+ messagesContainerStyle?: StyleProp<ViewStyle>
49
+ /* Input text; default is undefined, but if specified, it will override GiftedChat's internal state */
50
+ text?: string
51
+ /* Controls whether or not the message bubbles appear at the top of the chat */
52
+ alignTop?: boolean
53
+ /* enables the scrollToBottom Component */
54
+ scrollToBottom?: boolean
55
+ /* Scroll to bottom wrapper style */
56
+ scrollToBottomStyle?: StyleProp<ViewStyle>
57
+ initialText?: string
58
+ /* Placeholder when text is empty; default is 'Type a message...' */
59
+ placeholder?: string
60
+ /* Makes the composer not editable */
61
+ disableComposer?: boolean
62
+ /* User sending the messages: { _id, name, avatar } */
63
+ user?: User
64
+ /* Locale to localize the dates */
65
+ locale?: string
66
+ /* Format to use for rendering times; default is 'LT' */
67
+ timeFormat?: string
68
+ /* Format to use for rendering dates; default is 'll' */
69
+ dateFormat?: string
70
+ /* Format to use for rendering relative times; Today - for now. See more: https://day.js.org/docs/en/plugin/calendar */
71
+ dateFormatCalendar?: object
72
+ /* Enables the "Load earlier messages" button */
73
+ loadEarlier?: boolean
74
+ /* Display an ActivityIndicator when loading earlier messages */
75
+ isLoadingEarlier?: boolean
76
+ /* Determine whether to handle keyboard awareness inside the plugin. If you have your own keyboard handling outside the plugin set this to false; default is `true` */
77
+ isKeyboardInternallyHandled?: boolean
78
+ /* Whether to render an avatar for the current user; default is false, only show avatars for other users */
79
+ showUserAvatar?: boolean
80
+ /* When false, avatars will only be displayed when a consecutive message is from the same user on the same day; default is false */
81
+ showAvatarForEveryMessage?: boolean
82
+ /* Render the message avatar at the top of consecutive messages, rather than the bottom; default is false */
83
+ renderAvatarOnTop?: boolean
84
+ inverted?: boolean
85
+ /* Extra props to be passed to the <Image> component created by the default renderMessageImage */
86
+ imageProps?: MessageImageProps<TMessage>
87
+ /* Extra props to be passed to the MessageImage's Lightbox */
88
+ lightboxProps?: LightboxProps
89
+ /* Distance of the chat from the bottom of the screen (e.g. useful if you display a tab bar); default is 0 */
90
+ bottomOffset?: number
91
+ /* Focus on <TextInput> automatically when opening the keyboard; default is true */
92
+ focusOnInputWhenOpeningKeyboard?: boolean
93
+ /* Minimum height of the input toolbar; default is 44 */
94
+ minInputToolbarHeight?: number
95
+ /* Extra props to be passed to the messages <ListView>; some props can't be overridden, see the code in MessageContainer.render() for details */
96
+ listViewProps?: ListViewProps
97
+ /* Extra props to be passed to the <TextInput> */
98
+ textInputProps?: object
99
+ /* Determines whether the keyboard should stay visible after a tap; see <ScrollView> docs */
100
+ keyboardShouldPersistTaps?: 'always' | 'never' | 'handled'
101
+ /* Max message composer TextInput length */
102
+ maxInputLength?: number
103
+ /* Force send button */
104
+ alwaysShowSend?: boolean
105
+ /* Image style */
106
+ imageStyle?: StyleProp<ViewStyle>
107
+ /* This can be used to pass unknown data which needs to be re-rendered */
108
+ extraData?: object
109
+ /* composer min Height */
110
+ minComposerHeight?: number
111
+ /* composer min Height */
112
+ maxComposerHeight?: number
113
+ options?: { [key: string]: () => void }
114
+ optionTintColor?: string
115
+ quickReplyStyle?: StyleProp<ViewStyle>
116
+ quickReplyTextStyle?: StyleProp<TextStyle>
117
+ quickReplyContainerStyle?: StyleProp<ViewStyle>
118
+ /* optional prop used to place customView below text, image and video views; default is false */
119
+ isCustomViewBottom?: boolean
120
+ /* infinite scroll up when reach the top of messages container, automatically call onLoadEarlier function if exist */
121
+ infiniteScroll?: boolean
122
+ timeTextStyle?: LeftRightStyle<TextStyle>
123
+ /* Custom action sheet */
124
+ actionSheet?(): {
125
+ showActionSheetWithOptions: (
126
+ options: ActionSheetOptions,
127
+ callback: (buttonIndex: number) => void | Promise<void>,
128
+ ) => void
129
+ }
130
+ /* Callback when a message avatar is tapped */
131
+ onPressAvatar?(user: User): void
132
+ /* Callback when a message avatar is tapped */
133
+ onLongPressAvatar?(user: User): void
134
+ /* Generate an id for new messages. Defaults to UUID v4, generated by uuid */
135
+ messageIdGenerator?(message?: TMessage): string
136
+ /* Callback when sending a message */
137
+ onSend?(messages: TMessage[]): void
138
+ /* Callback when loading earlier messages */
139
+ onLoadEarlier?(): void
140
+ /* Render a loading view when initializing */
141
+ renderLoading?(): React.ReactNode
142
+ /* Custom "Load earlier messages" button */
143
+ renderLoadEarlier?(props: LoadEarlierProps): React.ReactNode
144
+ /* Custom message avatar; set to null to not render any avatar for the message */
145
+ renderAvatar?: null | ((props: AvatarProps<TMessage>) => React.ReactNode)
146
+ /* Custom message bubble */
147
+ renderBubble?(props: Bubble<TMessage>['props']): React.ReactNode
148
+ /* Custom system message */
149
+ renderSystemMessage?(props: SystemMessageProps<TMessage>): React.ReactNode
150
+ /* Callback when a message bubble is pressed; default is to do nothing */
151
+ onPress?(context: unknown, message: TMessage): void
152
+ /* Callback when a message bubble is long-pressed; default is to show an ActionSheet with "Copy Text" (see example using showActionSheetWithOptions()) */
153
+ onLongPress?(context: unknown, message: TMessage): void
154
+ /* Custom Username container */
155
+ renderUsername?(user: User): React.ReactNode
156
+ /* Reverses display order of messages; default is true */
157
+ /* Custom message container */
158
+ renderMessage?(message: MessageProps<TMessage>): React.ReactElement
159
+ /* Custom message text */
160
+ renderMessageText?(messageText: MessageTextProps<TMessage>): React.ReactNode
161
+ /* Custom message image */
162
+ renderMessageImage?(props: MessageImageProps<TMessage>): React.ReactNode
163
+ /* Custom message video */
164
+ renderMessageVideo?(props: MessageVideoProps<TMessage>): React.ReactNode
165
+ /* Custom message video */
166
+ renderMessageAudio?(props: MessageAudioProps<TMessage>): React.ReactNode
167
+ /* Custom view inside the bubble */
168
+ renderCustomView?(props: Bubble<TMessage>['props']): React.ReactNode
169
+ /* Custom day above a message */
170
+ renderDay?(props: DayProps): React.ReactNode
171
+ /* Custom time inside a message */
172
+ renderTime?(props: TimeProps<TMessage>): React.ReactNode
173
+ /* Custom footer component on the ListView, e.g. 'User is typing...' */
174
+ renderFooter?(): React.ReactNode
175
+ /* Custom component to render in the ListView when messages are empty */
176
+ renderChatEmpty?(): React.ReactNode
177
+ /* Custom component to render below the MessageContainer (separate from the ListView) */
178
+ renderChatFooter?(): React.ReactNode
179
+ /* Custom message composer container */
180
+ renderInputToolbar?(props: InputToolbarProps<TMessage>): React.ReactNode
181
+ /* Custom text input message composer */
182
+ renderComposer?(props: ComposerProps): React.ReactNode
183
+ /* Custom action button on the left of the message composer */
184
+ renderActions?(props: ActionsProps): React.ReactNode
185
+ /* Custom send button; you can pass children to the original Send component quite easily, for example to use a custom icon (example) */
186
+ renderSend?(props: SendProps<TMessage>): React.ReactNode
187
+ /* Custom second line of actions below the message composer */
188
+ renderAccessory?(props: InputToolbarProps<TMessage>): React.ReactNode
189
+ /* Callback when the Action button is pressed (if set, the default actionSheet will not be used) */
190
+ onPressActionButton?(): void
191
+ /* Callback when the input text changes */
192
+ onInputTextChanged?(text: string): void
193
+ /* Custom parse patterns for react-native-parsed-text used to linking message content (like URLs and phone numbers) */
194
+ parsePatterns?: (linkStyle?: TextStyle) => { type?: string, pattern?: RegExp, style?: StyleProp<TextStyle> | object, onPress?: unknown, renderText?: unknown }[]
195
+ onQuickReply?(replies: Reply[]): void
196
+ renderQuickReplies?(
197
+ quickReplies: QuickRepliesProps<TMessage>,
198
+ ): React.ReactNode
199
+ renderQuickReplySend?(): React.ReactNode
200
+ /* Scroll to bottom custom component */
201
+ scrollToBottomComponent?(): React.ReactNode
202
+ shouldUpdateMessage?(
203
+ props: MessageProps<TMessage>,
204
+ nextProps: MessageProps<TMessage>,
205
+ ): boolean
206
+ }
@@ -1,4 +1,3 @@
1
- import PropTypes from 'prop-types'
2
1
  import React, { useMemo } from 'react'
3
2
  import { StyleSheet, View, StyleProp, ViewStyle } from 'react-native'
4
3
 
@@ -6,8 +5,7 @@ import { Composer, ComposerProps } from './Composer'
6
5
  import { Send, SendProps } from './Send'
7
6
  import { Actions, ActionsProps } from './Actions'
8
7
  import Color from './Color'
9
- import { StylePropType } from './utils'
10
- import { IMessage } from './Models'
8
+ import { IMessage } from './types'
11
9
 
12
10
  export interface InputToolbarProps<TMessage extends IMessage> {
13
11
  options?: { [key: string]: () => void }
@@ -86,17 +84,6 @@ export function InputToolbar<TMessage extends IMessage = IMessage> (
86
84
  )
87
85
  }
88
86
 
89
- InputToolbar.propTypes = {
90
- renderAccessory: PropTypes.func,
91
- renderActions: PropTypes.func,
92
- renderSend: PropTypes.func,
93
- renderComposer: PropTypes.func,
94
- onPressActionButton: PropTypes.func,
95
- containerStyle: StylePropType,
96
- primaryStyle: StylePropType,
97
- accessoryStyle: StylePropType,
98
- }
99
-
100
87
  const styles = StyleSheet.create({
101
88
  container: {
102
89
  borderTopWidth: StyleSheet.hairlineWidth,
@@ -1,4 +1,3 @@
1
- import PropTypes from 'prop-types'
2
1
  import React from 'react'
3
2
  import {
4
3
  ActivityIndicator,
@@ -12,7 +11,7 @@ import {
12
11
  TextStyle,
13
12
  } from 'react-native'
14
13
  import Color from './Color'
15
- import { StylePropType } from './utils'
14
+ import stylesCommon from './styles'
16
15
 
17
16
  const styles = StyleSheet.create({
18
17
  container: {
@@ -21,8 +20,6 @@ const styles = StyleSheet.create({
21
20
  marginBottom: 10,
22
21
  },
23
22
  wrapper: {
24
- alignItems: 'center',
25
- justifyContent: 'center',
26
23
  backgroundColor: Color.defaultColor,
27
24
  borderRadius: 15,
28
25
  height: 30,
@@ -73,7 +70,7 @@ export function LoadEarlier ({
73
70
  disabled={isLoadingEarlier}
74
71
  accessibilityRole='button'
75
72
  >
76
- <View style={[styles.wrapper, wrapperStyle]}>
73
+ <View style={[stylesCommon.centerItems, styles.wrapper, wrapperStyle]}>
77
74
  {isLoadingEarlier
78
75
  ? (
79
76
  <View>
@@ -94,15 +91,3 @@ export function LoadEarlier ({
94
91
  </TouchableOpacity>
95
92
  )
96
93
  }
97
-
98
- LoadEarlier.propTypes = {
99
- onLoadEarlier: PropTypes.func,
100
- isLoadingEarlier: PropTypes.bool,
101
- label: PropTypes.string,
102
- containerStyle: StylePropType,
103
- wrapperStyle: StylePropType,
104
- textStyle: StylePropType,
105
- activityIndicatorStyle: StylePropType,
106
- activityIndicatorColor: PropTypes.string,
107
- activityIndicatorSize: PropTypes.string,
108
- }
@@ -0,0 +1,135 @@
1
+ import React, { memo, useCallback } from 'react'
2
+ import { View } from 'react-native'
3
+ import isEqual from 'lodash.isequal'
4
+
5
+ import { Avatar } from '../Avatar'
6
+ import Bubble from '../Bubble'
7
+ import { SystemMessage } from '../SystemMessage'
8
+
9
+ import { isSameUser } from '../utils'
10
+ import { IMessage } from '../types'
11
+ import { MessageProps } from './types'
12
+ import styles from './styles'
13
+
14
+ export * from './types'
15
+
16
+ let Message: React.FC<MessageProps<IMessage>> = (props: MessageProps<IMessage>) => {
17
+ const {
18
+ currentMessage,
19
+ renderBubble: renderBubbleProp,
20
+ renderSystemMessage: renderSystemMessageProp,
21
+ onMessageLayout,
22
+ nextMessage,
23
+ position,
24
+ containerStyle,
25
+ user,
26
+ showUserAvatar,
27
+ } = props
28
+
29
+ const renderBubble = useCallback(() => {
30
+ const {
31
+ /* eslint-disable @typescript-eslint/no-unused-vars */
32
+ containerStyle,
33
+ onMessageLayout,
34
+ /* eslint-enable @typescript-eslint/no-unused-vars */
35
+ ...rest
36
+ } = props
37
+
38
+ if (renderBubbleProp)
39
+ return renderBubbleProp(rest)
40
+
41
+ return <Bubble {...rest} />
42
+ }, [props, renderBubbleProp])
43
+
44
+ const renderSystemMessage = useCallback(() => {
45
+ const {
46
+ /* eslint-disable @typescript-eslint/no-unused-vars */
47
+ containerStyle,
48
+ onMessageLayout,
49
+ /* eslint-enable @typescript-eslint/no-unused-vars */
50
+ ...rest
51
+ } = props
52
+
53
+ if (renderSystemMessageProp)
54
+ return renderSystemMessageProp(rest)
55
+
56
+ return <SystemMessage {...rest} />
57
+ }, [props, renderSystemMessageProp])
58
+
59
+ const renderAvatar = useCallback(() => {
60
+ if (
61
+ user?._id &&
62
+ currentMessage?.user &&
63
+ user._id === currentMessage.user._id &&
64
+ !showUserAvatar
65
+ )
66
+ return null
67
+
68
+ if (currentMessage?.user?.avatar === null)
69
+ return null
70
+
71
+ const {
72
+ /* eslint-disable @typescript-eslint/no-unused-vars */
73
+ containerStyle,
74
+ onMessageLayout,
75
+ /* eslint-enable @typescript-eslint/no-unused-vars */
76
+ ...rest
77
+ } = props
78
+
79
+ return <Avatar {...rest} />
80
+ }, [
81
+ props,
82
+ user,
83
+ currentMessage,
84
+ showUserAvatar,
85
+ ])
86
+
87
+ if (!currentMessage)
88
+ return null
89
+
90
+ const sameUser = isSameUser(currentMessage, nextMessage!)
91
+
92
+ return (
93
+ <View onLayout={onMessageLayout}>
94
+ {currentMessage.system
95
+ ? (
96
+ renderSystemMessage()
97
+ )
98
+ : (
99
+ <View
100
+ style={[
101
+ styles[position].container,
102
+ { marginBottom: sameUser ? 2 : 10 },
103
+ !props.inverted && { marginBottom: 2 },
104
+ containerStyle?.[position],
105
+ ]}
106
+ >
107
+ {position === 'left' ? renderAvatar() : null}
108
+ {renderBubble()}
109
+ {position === 'right' ? renderAvatar() : null}
110
+ </View>
111
+ )}
112
+ </View>
113
+ )
114
+ }
115
+
116
+ Message = memo(Message, (props, nextProps) => {
117
+ const next = nextProps.currentMessage!
118
+ const current = props.currentMessage!
119
+ const { previousMessage, nextMessage } = props
120
+ const nextPropsMessage = nextProps.nextMessage
121
+ const nextPropsPreviousMessage = nextProps.previousMessage
122
+
123
+ let shouldUpdate =
124
+ props.shouldUpdateMessage?.(props, nextProps) || false
125
+
126
+ shouldUpdate =
127
+ shouldUpdate ||
128
+ !isEqual(current, next) ||
129
+ !isEqual(previousMessage, nextPropsPreviousMessage) ||
130
+ !isEqual(nextMessage, nextPropsMessage)
131
+
132
+ return shouldUpdate
133
+ })
134
+
135
+ export default Message
@@ -0,0 +1,22 @@
1
+ import { StyleSheet } from 'react-native'
2
+
3
+ export default {
4
+ left: StyleSheet.create({
5
+ container: {
6
+ flexDirection: 'row',
7
+ alignItems: 'flex-end',
8
+ justifyContent: 'flex-start',
9
+ marginLeft: 8,
10
+ marginRight: 0,
11
+ },
12
+ }),
13
+ right: StyleSheet.create({
14
+ container: {
15
+ flexDirection: 'row',
16
+ alignItems: 'flex-end',
17
+ justifyContent: 'flex-end',
18
+ marginLeft: 0,
19
+ marginRight: 8,
20
+ },
21
+ }),
22
+ }
@@ -0,0 +1,26 @@
1
+ import { ViewStyle, LayoutChangeEvent } from 'react-native'
2
+ import { AvatarProps } from '../Avatar'
3
+ import { SystemMessageProps } from '../SystemMessage'
4
+ import { DayProps } from '../Day'
5
+ import { IMessage, User, LeftRightStyle } from '../types'
6
+ import Bubble from '../Bubble'
7
+
8
+ export interface MessageProps<TMessage extends IMessage> {
9
+ showUserAvatar?: boolean
10
+ position: 'left' | 'right'
11
+ currentMessage: TMessage
12
+ nextMessage?: TMessage
13
+ previousMessage?: TMessage
14
+ user: User
15
+ inverted?: boolean
16
+ containerStyle?: LeftRightStyle<ViewStyle>
17
+ renderBubble?(props: Bubble['props']): React.ReactNode
18
+ renderDay?(props: DayProps): React.ReactNode
19
+ renderSystemMessage?(props: SystemMessageProps<TMessage>): React.ReactNode
20
+ renderAvatar?(props: AvatarProps<TMessage>): React.ReactNode
21
+ shouldUpdateMessage?(
22
+ props: MessageProps<IMessage>,
23
+ nextProps: MessageProps<IMessage>,
24
+ ): boolean
25
+ onMessageLayout?(event: LayoutChangeEvent): void
26
+ }
@@ -9,10 +9,7 @@ export function MessageAudio () {
9
9
  {'Audio is not implemented by GiftedChat.'}
10
10
  </Text>
11
11
  <Text style={{ color: Color.alizarin, fontWeight: '600' }}>
12
- {
13
- 'You need to provide your own implementation by using renderMessageAudio'
14
- }
15
- {'prop.'}
12
+ {'\nYou need to provide your own implementation by using renderMessageAudio prop.'}
16
13
  </Text>
17
14
  </View>
18
15
  )
@@ -0,0 +1,143 @@
1
+ import React, { useCallback, useEffect, useMemo, useState } from 'react'
2
+ import { LayoutChangeEvent } from 'react-native'
3
+ import Animated, { interpolate, useAnimatedStyle, useDerivedValue, useSharedValue, useAnimatedReaction, withTiming, runOnJS } from 'react-native-reanimated'
4
+ import { Day } from '../../../Day'
5
+ import { isSameDay } from '../../../utils'
6
+ import { useScrolledPosition, useTopOffset } from '../Item'
7
+ import { DayAnimatedProps } from './types'
8
+
9
+ import stylesCommon from '../../../styles'
10
+ import styles from './styles'
11
+
12
+ export * from './types'
13
+
14
+ const DayAnimated = ({ scrolledY, daysPositions, listHeight, renderDay, messages, isLoadingEarlier, ...rest }: DayAnimatedProps) => {
15
+ const opacity = useSharedValue(0)
16
+ const fadeOutOpacityTimeoutId = useSharedValue<ReturnType<typeof setTimeout> | undefined>(undefined)
17
+ const containerHeight = useSharedValue(0)
18
+
19
+ const isScrolledOnMount = useSharedValue(false)
20
+ const isLoadingEarlierAnim = useSharedValue(isLoadingEarlier)
21
+
22
+ const daysPositionsArray = useDerivedValue(() => Object.values(daysPositions.value).sort((a, b) => a.y - b.y))
23
+
24
+ const [createdAt, setCreatedAt] = useState<number | undefined>()
25
+
26
+ const dayTopOffset = useMemo(() => 10, [])
27
+ const dayBottomMargin = useMemo(() => 10, [])
28
+ const scrolledPosition = useScrolledPosition(listHeight, scrolledY, containerHeight, dayBottomMargin, dayTopOffset)
29
+ const topOffset = useTopOffset(listHeight, scrolledY, daysPositions, containerHeight, dayBottomMargin, dayTopOffset)
30
+
31
+ const messagesDates = useMemo(() => {
32
+ const messagesDates: number[] = []
33
+
34
+ for (let i = 1; i < messages.length; i++) {
35
+ const previousMessage = messages[i - 1]
36
+ const message = messages[i]
37
+
38
+ if (!isSameDay(previousMessage, message) || !messagesDates.includes(new Date(message.createdAt).getTime()))
39
+ messagesDates.push(new Date(message.createdAt).getTime())
40
+ }
41
+
42
+ return messagesDates
43
+ }, [messages])
44
+
45
+ const createdAtDate = useDerivedValue(() => {
46
+ for (let i = 0; i < daysPositionsArray.value.length; i++) {
47
+ const day = daysPositionsArray.value[i]
48
+ const dayPosition = day.y + day.height - containerHeight.value - dayBottomMargin
49
+
50
+ if (scrolledPosition.value < dayPosition)
51
+ return day.createdAt
52
+ }
53
+
54
+ return messagesDates[messagesDates.length - 1]
55
+ }, [daysPositionsArray, scrolledPosition, messagesDates, containerHeight, dayBottomMargin])
56
+
57
+ const style = useAnimatedStyle(() => ({
58
+ top: interpolate(
59
+ topOffset.value,
60
+ [-dayTopOffset, -0.0001, 0, isLoadingEarlierAnim.value ? 0 : containerHeight.value + dayTopOffset],
61
+ [dayTopOffset, dayTopOffset, -containerHeight.value, isLoadingEarlierAnim.value ? -containerHeight.value : dayTopOffset],
62
+ 'clamp'
63
+ ),
64
+ }), [topOffset, containerHeight, dayTopOffset, isLoadingEarlierAnim])
65
+
66
+ const contentStyle = useAnimatedStyle(() => ({
67
+ opacity: opacity.value,
68
+ }), [opacity])
69
+
70
+ const fadeOut = useCallback(() => {
71
+ 'worklet'
72
+
73
+ opacity.value = withTiming(0, { duration: 500 })
74
+ }, [opacity])
75
+
76
+ const scheduleFadeOut = useCallback(() => {
77
+ clearTimeout(fadeOutOpacityTimeoutId.value)
78
+
79
+ fadeOutOpacityTimeoutId.value = setTimeout(fadeOut, 500)
80
+ }, [fadeOut, fadeOutOpacityTimeoutId])
81
+
82
+ const handleLayout = useCallback(({ nativeEvent }: LayoutChangeEvent) => {
83
+ containerHeight.value = nativeEvent.layout.height
84
+ }, [containerHeight])
85
+
86
+ useAnimatedReaction(
87
+ () => [scrolledY.value, daysPositionsArray],
88
+ (value, prevValue) => {
89
+ if (!isScrolledOnMount.value) {
90
+ isScrolledOnMount.value = true
91
+ return
92
+ }
93
+
94
+ if (value[0] === prevValue?.[0])
95
+ return
96
+
97
+ opacity.value = withTiming(1, { duration: 500 })
98
+
99
+ runOnJS(scheduleFadeOut)()
100
+ },
101
+ [scrolledY, scheduleFadeOut, daysPositionsArray]
102
+ )
103
+
104
+ useAnimatedReaction(
105
+ () => createdAtDate.value,
106
+ (value, prevValue) => {
107
+ if (value && value !== prevValue)
108
+ runOnJS(setCreatedAt)(value)
109
+ },
110
+ [createdAtDate]
111
+ )
112
+
113
+ useEffect(() => {
114
+ isLoadingEarlierAnim.value = isLoadingEarlier
115
+ }, [isLoadingEarlierAnim, isLoadingEarlier])
116
+
117
+ if (!createdAt)
118
+ return null
119
+
120
+ return (
121
+ <Animated.View
122
+ style={[stylesCommon.centerItems, styles.dayAnimated, style]}
123
+ onLayout={handleLayout}
124
+ >
125
+ <Animated.View
126
+ style={contentStyle}
127
+ pointerEvents='none'
128
+ >
129
+ {
130
+ renderDay
131
+ ? renderDay({ ...rest, createdAt })
132
+ : <Day
133
+ {...rest}
134
+ containerStyle={[styles.dayAnimatedDayContainerStyle, rest.containerStyle]}
135
+ createdAt={createdAt}
136
+ />
137
+ }
138
+ </Animated.View>
139
+ </Animated.View>
140
+ )
141
+ }
142
+
143
+ export default DayAnimated
@@ -0,0 +1,12 @@
1
+ import { StyleSheet } from 'react-native'
2
+
3
+ export default StyleSheet.create({
4
+ dayAnimated: {
5
+ position: 'absolute',
6
+ width: '100%',
7
+ },
8
+ dayAnimatedDayContainerStyle: {
9
+ marginTop: 0,
10
+ marginBottom: 0,
11
+ },
12
+ })
@@ -0,0 +1,12 @@
1
+ import { DayProps } from '../../../Day'
2
+ import { IMessage } from '../../../types'
3
+ import { DaysPositions } from '../../types'
4
+
5
+ export interface DayAnimatedProps extends Omit<DayProps, 'createdAt'> {
6
+ scrolledY: { value: number }
7
+ daysPositions: { value: DaysPositions }
8
+ listHeight: { value: number }
9
+ renderDay?: (props: DayProps) => React.ReactNode
10
+ messages: IMessage[]
11
+ isLoadingEarlier: boolean
12
+ }