react-native-gifted-chat 2.8.2-alpha.6 → 3.0.0-alpha.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 (66) hide show
  1. package/README.md +190 -269
  2. package/package.json +2 -1
  3. package/src/Actions.tsx +1 -1
  4. package/src/Avatar.tsx +12 -12
  5. package/src/Bubble/index.tsx +14 -16
  6. package/src/Bubble/styles.ts +1 -1
  7. package/src/Bubble/types.ts +26 -27
  8. package/src/Color.ts +1 -1
  9. package/src/Composer.tsx +1 -4
  10. package/src/Day/styles.ts +1 -1
  11. package/src/GiftedAvatar.tsx +2 -2
  12. package/src/GiftedChat/index.tsx +26 -61
  13. package/src/GiftedChat/types.ts +40 -49
  14. package/src/InputToolbar.tsx +28 -19
  15. package/src/LoadEarlierMessages.tsx +1 -1
  16. package/src/Message/index.tsx +11 -14
  17. package/src/Message/types.ts +8 -12
  18. package/src/MessageAudio.tsx +1 -1
  19. package/src/MessageContainer/components/DayAnimated/index.tsx +1 -3
  20. package/src/MessageContainer/components/DayAnimated/types.ts +1 -1
  21. package/src/MessageContainer/components/Item/index.tsx +9 -11
  22. package/src/MessageContainer/components/Item/types.ts +1 -1
  23. package/src/MessageContainer/index.tsx +32 -36
  24. package/src/MessageContainer/styles.ts +1 -1
  25. package/src/MessageContainer/types.ts +12 -16
  26. package/src/MessageImage.tsx +1 -1
  27. package/src/MessageText.tsx +1 -1
  28. package/src/MessageVideo.tsx +1 -1
  29. package/src/Models.ts +63 -0
  30. package/src/QuickReplies.tsx +2 -2
  31. package/src/Send.tsx +31 -32
  32. package/src/SystemMessage.tsx +2 -2
  33. package/src/Time.tsx +6 -6
  34. package/src/TypingIndicator/index.tsx +1 -3
  35. package/src/TypingIndicator/styles.ts +1 -1
  36. package/src/__tests__/Actions.test.tsx +1 -1
  37. package/src/__tests__/Avatar.test.tsx +7 -2
  38. package/src/__tests__/Bubble.test.tsx +3 -7
  39. package/src/__tests__/Color.test.tsx +1 -1
  40. package/src/__tests__/Composer.test.tsx +1 -1
  41. package/src/__tests__/Day.test.tsx +3 -3
  42. package/src/__tests__/DayAnimated.test.tsx +5 -11
  43. package/src/__tests__/GiftedAvatar.test.tsx +1 -1
  44. package/src/__tests__/GiftedChat.test.tsx +1 -1
  45. package/src/__tests__/InputToolbar.test.tsx +1 -1
  46. package/src/__tests__/LoadEarlier.test.tsx +2 -2
  47. package/src/__tests__/Message.test.tsx +7 -13
  48. package/src/__tests__/MessageContainer.test.tsx +4 -4
  49. package/src/__tests__/MessageImage.test.tsx +2 -2
  50. package/src/__tests__/MessageText.test.tsx +3 -2
  51. package/src/__tests__/Send.test.tsx +2 -2
  52. package/src/__tests__/SystemMessage.test.tsx +1 -1
  53. package/src/__tests__/Time.test.tsx +1 -1
  54. package/src/__tests__/__snapshots__/Actions.test.tsx.snap +2 -86
  55. package/src/__tests__/__snapshots__/Bubble.test.tsx.snap +1 -1
  56. package/src/__tests__/__snapshots__/Day.test.tsx.snap +96 -2
  57. package/src/__tests__/__snapshots__/InputToolbar.test.tsx.snap +1 -1
  58. package/src/__tests__/__snapshots__/LoadEarlier.test.tsx.snap +3 -89
  59. package/src/__tests__/__snapshots__/Message.test.tsx.snap +43 -4
  60. package/src/__tests__/__snapshots__/MessageText.test.tsx.snap +1 -1
  61. package/src/__tests__/__snapshots__/Send.test.tsx.snap +10 -142
  62. package/src/__tests__/data.ts +2 -2
  63. package/src/components/TouchableOpacity.tsx +19 -8
  64. package/src/index.ts +19 -1
  65. package/src/types.ts +1 -63
  66. package/src/utils.ts +23 -2
package/README.md CHANGED
@@ -1,5 +1,5 @@
1
- <p align="center" >
2
- <p align="center" >
1
+ <p align="center">
2
+ <p align="center">
3
3
  <a href="https://reactnative.gallery/FaridSafi/gifted-chat">
4
4
     <img alt="react-native-gifted-chat" src="https://thumbs.gfycat.com/AbsoluteSadDobermanpinscher-size_restricted.gif" width="260" height="510" />
5
5
  </a>
@@ -136,34 +136,7 @@ npx pod-install
136
136
 
137
137
  Follow guide: [react-native-reanimated](https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/getting-started/#step-2-add-reanimateds-babel-plugin)
138
138
 
139
- ## Testing
140
- `TEST_ID` is exported as constants that can be used in your testing library of choice
141
-
142
- Gifted Chat uses `onLayout` to determine the height of the chat container. To trigger `onLayout` during your tests, you can run the following bits of code.
143
-
144
- ```typescript
145
- const WIDTH = 200; // or any number
146
- const HEIGHT = 2000; // or any number
147
-
148
- const loadingWrapper = getByTestId(TEST_ID.LOADING_WRAPPER)
149
- fireEvent(loadingWrapper, 'layout', {
150
- nativeEvent: {
151
- layout: {
152
- width: WIDTH,
153
- height: HEIGHT,
154
- },
155
- },
156
- })
157
- ```
158
-
159
- ## You have a question?
160
-
161
- 1. Please check this readme and may find a response
162
- 1. Please ask on StackOverflow first: https://stackoverflow.com/questions/tagged/react-native-gifted-chat
163
- 1. Find response on existing issues
164
- 1. Try to keep issues for issues
165
-
166
- ## Example
139
+ ## Simple example
167
140
 
168
141
  ```jsx
169
142
  import React, { useState, useCallback, useEffect } from 'react'
@@ -212,222 +185,83 @@ export function Example() {
212
185
  }
213
186
  ```
214
187
 
215
- ## Advanced example
188
+ ## Different examples
216
189
 
217
- See [`examples`](example) for a working demo!
190
+ Check out code of [`examples`](example)
218
191
 
219
- ## "Slack" example
192
+ ## Data structure
220
193
 
221
- See the files in [`example/example-slack-message`](example/example-slack-message) for an example of how to override the default UI to make something that looks more like Slack -- with usernames displayed and all messages on the left.
194
+ Messages, system messages, quick replies etc.: [data structure](src/Models.ts)
222
195
 
223
- ## Message object
196
+ ## Props
224
197
 
225
- > e.g. Chat Message
198
+ ### Core Configuration
226
199
 
227
- ```ts
228
- export interface IMessage {
229
- _id: string | number
230
- text: string
231
- createdAt: Date | number
232
- user: User
233
- image?: string
234
- video?: string
235
- audio?: string
236
- system?: boolean
237
- sent?: boolean
238
- received?: boolean
239
- pending?: boolean
240
- quickReplies?: QuickReplies
241
- }
242
- ```
200
+ - **`messages`** _(Array)_ - Messages to display
201
+ - **`user`** _(Object)_ - User sending the messages: `{ _id, name, avatar }`
202
+ - **`onSend`** _(Function)_ - Callback when sending a message
203
+ - **`messageIdGenerator`** _(Function)_ - Generate an id for new messages. Defaults to a simple random string generator.
204
+ - **`locale`** _(String)_ - Locale to localize the dates. You need first to import the locale you need (ie. `require('dayjs/locale/de')` or `import 'dayjs/locale/fr'`)
243
205
 
244
- ```js
245
- {
246
- _id: 1,
247
- text: 'My message',
248
- createdAt: new Date(Date.UTC(2016, 5, 11, 17, 20, 0)),
249
- user: {
250
- _id: 2,
251
- name: 'React Native',
252
- avatar: 'https://facebook.github.io/react/img/logo_og.png',
253
- },
254
- image: 'https://facebook.github.io/react/img/logo_og.png',
255
- // You can also add a video prop:
256
- video: 'http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ElephantsDream.mp4',
257
- // Mark the message as sent, using one tick
258
- sent: true,
259
- // Mark the message as received, using two tick
260
- received: true,
261
- // Mark the message as pending with a clock loader
262
- pending: true,
263
- // Any additional custom parameters are passed through
264
- }
265
- ```
206
+ ### Refs
266
207
 
267
- > e.g. System Message
208
+ - **`messageContainerRef`** _(FlatList ref)_ - Ref to the flatlist
209
+ - **`textInputRef`** _(TextInput ref)_ - Ref to the text input
268
210
 
269
- ```js
270
- {
271
- _id: 1,
272
- text: 'This is a system message',
273
- createdAt: new Date(Date.UTC(2016, 5, 11, 17, 20, 0)),
274
- system: true,
275
- // Any additional custom parameters are passed through
276
- }
277
- ```
211
+ ### Keyboard & Layout
278
212
 
279
- > e.g. Chat Message with Quick Reply options
213
+ - **`keyboardBottomOffset`** _(Integer)_ - Distance between the bottom of the screen and bottom of the `GiftedChat` component. Useful when you have a tab bar or navigation bar; default is `0`. Needed for correct keyboard avoiding behavior. Without it you might see gap between the keyboard and the input toolbar if you have a tab bar, navigation bar, or safe area.
214
+ - **`isKeyboardInternallyHandled`** _(Bool)_ - 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`
215
+ - **`shouldFocusInputOnKeyboardOpen`** _(Bool)_ - Focus on <TextInput> automatically when opening the keyboard; default `true`
216
+ - **`isAlignedTop`** _(Boolean)_ Controls whether or not the message bubbles appear at the top of the chat (Default is false - bubbles align to bottom)
217
+ - **`isInverted`** _(Bool)_ - Reverses display order of `messages`; default is `true`
280
218
 
281
- See PR [#1211](https://github.com/FaridSafi/react-native-gifted-chat/pull/1211)
219
+ ### Text Input & Composer
282
220
 
283
- ```ts
284
- interface Reply {
285
- title: string
286
- value: string
287
- messageId?: number | string
288
- }
221
+ - **`text`** _(String)_ - Input text; default is `undefined`, but if specified, it will override GiftedChat's internal state. Useful for managing text state outside of GiftedChat (e.g. with Redux). Don't forget to implement `textInputProps.onChangeText` to update the text state.
222
+ - **`initialText`** _(String)_ - Initial text to display in the input field
223
+ - **`isSendButtonAlwaysVisible`** _(Bool)_ - Always show send button in input text composer; default `false`, show only when text input is not empty
224
+ - **`minComposerHeight`** _(Object)_ - Custom min-height of the composer.
225
+ - **`maxComposerHeight`** _(Object)_ - Custom max height of the composer.
226
+ - **`minInputToolbarHeight`** _(Integer)_ - Minimum height of the input toolbar; default is `44`
227
+ - **`renderInputToolbar`** _(Component | Function)_ - Custom message composer container
228
+ - **`renderComposer`** _(Component | Function)_ - Custom text input message composer
229
+ - **`renderSend`** _(Component | Function)_ - Custom send button; you can pass children to the original `Send` component quite easily, for example, to use a custom icon ([example](https://github.com/FaridSafi/react-native-gifted-chat/pull/487))
230
+ - **`renderActions`** _(Component | Function)_ - Custom action button on the left of the message composer
231
+ - **`renderAccessory`** _(Component | Function)_ - Custom second line of actions below the message composer
232
+ - **`textInputProps`** _(Object)_ - props to be passed to the [`<TextInput>`](https://reactnative.dev/docs/textinput.html).
289
233
 
290
- interface QuickReplies {
291
- type: 'radio' | 'checkbox'
292
- values: Reply[]
293
- keepIt?: boolean
294
- }
295
- ```
234
+ ### Actions & Action Sheet
296
235
 
297
- ```js
298
- {
299
- _id: 1,
300
- text: 'This is a quick reply. Do you love Gifted Chat? (radio) KEEP IT',
301
- createdAt: new Date(),
302
- quickReplies: {
303
- type: 'radio', // or 'checkbox',
304
- keepIt: true,
305
- values: [
306
- {
307
- title: '😋 Yes',
308
- value: 'yes',
309
- },
310
- {
311
- title: '📷 Yes, let me show you with a picture!',
312
- value: 'yes_picture',
313
- },
314
- {
315
- title: '😞 Nope. What?',
316
- value: 'no',
317
- },
318
- ],
319
- },
320
- user: {
321
- _id: 2,
322
- name: 'React Native',
323
- },
324
- },
325
- {
326
- _id: 2,
327
- text: 'This is a quick reply. Do you love Gifted Chat? (checkbox)',
328
- createdAt: new Date(),
329
- quickReplies: {
330
- type: 'checkbox', // or 'radio',
331
- values: [
332
- {
333
- title: 'Yes',
334
- value: 'yes',
335
- },
336
- {
337
- title: 'Yes, let me show you with a picture!',
338
- value: 'yes_picture',
339
- },
340
- {
341
- title: 'Nope. What?',
342
- value: 'no',
343
- },
344
- ],
345
- },
346
- user: {
347
- _id: 2,
348
- name: 'React Native',
349
- },
350
- }
351
- ```
236
+ - **`onPressActionButton`** _(Function)_ - Callback when the Action button is pressed (if set, the default `actionSheet` will not be used)
237
+ - **`actionSheet`** _(Function)_ - Custom action sheet interface for showing action options
238
+ - **`actions`** _(Array)_ - Custom action options for the input toolbar action button; array of objects with `title` (string) and `action` (function) properties
239
+ - **`actionSheetOptionTintColor`** _(String)_ - Tint color for action sheet options
352
240
 
353
- ## Props
241
+ ### Messages & Message Container
354
242
 
355
- - **`messageContainerRef`** _(FlatList ref)_ - Ref to the flatlist
356
- - **`textInputRef`** _(TextInput ref)_ - Ref to the text input
357
- - **`messages`** _(Array)_ - Messages to display
358
243
  - **`messagesContainerStyle`** _(Object)_ - Custom style for the messages container
359
- - **`isTyping`** _(Bool)_ - Typing Indicator state; default `false`. If you use`renderFooter` it will override this.
360
- - **`keyboardBottomOffset`** _(Integer)_ - Distance between the bottom of the screen and bottom of the `GiftedChat` component. Useful when you have a tab bar or navigation bar; default is `0`. Needed for correct keyboard avoiding behavior. Without it you might see gap between the keyboard and the input toolbar if you have a tab bar, navigation bar, or safe area.
361
- - **`isKeyboardInternallyHandled`** _(Bool)_ - 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`
362
- - **`text`** _(String)_ - Input text; default is `undefined`, but if specified, it will override GiftedChat's internal state (e.g. for redux; [see notes below](#notes-for-redux))
363
- - **`initialText`** _(String)_ - Initial text to display in the input field
364
- - **`onInputTextChanged`** _(Function)_ - Callback when the input text changes
365
- - **`messageIdGenerator`** _(Function)_ - Generate an id for new messages. Defaults to UUID v4, generated by [uuid](https://github.com/kelektiv/node-uuid)
366
- - **`user`** _(Object)_ - User sending the messages: `{ _id, name, avatar }`
367
- - **`onSend`** _(Function)_ - Callback when sending a message
368
- - **`alwaysShowSend`** _(Bool)_ - Always show send button in input text composer; default `false`, show only when text input is not empty
369
- - **`locale`** _(String)_ - Locale to localize the dates. You need first to import the locale you need (ie. `require('dayjs/locale/de')` or `import 'dayjs/locale/fr'`)
370
- - **`timeFormat`** _(String)_ - Format to use for rendering times; default is `'LT'` (see [Day.js Format](https://day.js.org/docs/en/display/format))
371
- - **`dateFormat`** _(String)_ - Format to use for rendering dates; default is `'D MMMM'` (see [Day.js Format](https://day.js.org/docs/en/display/format))
372
- - **`dateFormatCalendar`** _(Object)_ - Format to use for rendering relative times; default is `{ sameDay: '[Today]' }` (see [Day.js Calendar](https://day.js.org/docs/en/plugin/calendar))
373
- - **`loadEarlierMessagesProps`** _(Object)_ - Props to pass to the LoadEarlierMessages component. The button is only visible when `isAvailable` is `true`. Supports the following props:
374
- - `isAvailable` - Controls button visibility (default: false)
375
- - `onPress` - Callback when button is pressed
376
- - `isLoading` - Display loading indicator (default: false)
377
- - `isInfiniteScrollEnabled` - Enable infinite scroll up when reaching the top of messages container, automatically calls `onPress` (not yet supported for web)
378
- - `label` - Override the default "Load earlier messages" text
379
- - `containerStyle` - Custom style for the button container
380
- - `wrapperStyle` - Custom style for the button wrapper
381
- - `textStyle` - Custom style for the button text
382
- - `activityIndicatorStyle` - Custom style for the loading indicator
383
- - `activityIndicatorColor` - Color of the loading indicator (default: 'white')
384
- - `activityIndicatorSize` - Size of the loading indicator (default: 'small')
385
- - **`renderLoading`** _(Function)_ - Render a loading view when initializing
386
- - **`renderLoadEarlier`** _(Function)_ - Custom "Load earlier messages" button
387
- - **`renderAvatar`** _(Function)_ - Custom message avatar; set to `null` to not render any avatar for the message
388
- - **`showUserAvatar`** _(Bool)_ - Whether to render an avatar for the current user; default is `false`, only show avatars for other users
389
- - **`showAvatarForEveryMessage`** _(Bool)_ - When false, avatars will only be displayed when a consecutive message is from the same user on the same day; default is `false`
390
- - **`onPressAvatar`** _(Function(`user`))_ - Callback when a message avatar is tapped
391
- - **`onLongPressAvatar`** _(Function(`user`))_ - Callback when a message avatar is long-pressed
392
- - **`renderAvatarOnTop`** _(Bool)_ - Render the message avatar at the top of consecutive messages, rather than the bottom; default is `false`
393
- - **`renderBubble`** _(Function)_ - Custom message bubble
394
- - **`renderTicks`** _(Function(`message`))_ - Custom ticks indicator to display message status
395
- - **`renderSystemMessage`** _(Function)_ - Custom system message
244
+ - **`renderMessage`** _(Component | Function)_ - Custom message container
245
+ - **`renderLoading`** _(Component | Function)_ - Render a loading view when initializing
246
+ - **`renderChatEmpty`** _(Component | Function)_ - Custom component to render in the ListView when messages are empty
247
+ - **`renderChatFooter`** _(Component | Function)_ - Custom component to render below the MessageContainer (separate from the ListView)
248
+ - **`listProps`** _(Object)_ - Extra props to be passed to the messages [`<FlatList>`](https://reactnative.dev/docs/flatlist.html); some props can't be overridden, see the code in `MessageContainer.render()` for details
249
+
250
+ ### Message Bubbles & Content
251
+
252
+ - **`renderBubble`** _(Component | Function)_ - Custom message bubble
253
+ - **`renderMessageText`** _(Component | Function)_ - Custom message text
254
+ - **`renderMessageImage`** _(Component | Function)_ - Custom message image
255
+ - **`renderMessageVideo`** _(Component | Function)_ - Custom message video
256
+ - **`renderMessageAudio`** _(Component | Function)_ - Custom message audio
257
+ - **`renderCustomView`** _(Component | Function)_ - Custom view inside the bubble
258
+ - **`isCustomViewBottom`** _(Bool)_ - Determine whether renderCustomView is displayed before or after the text, image and video views; default is `false`
259
+ - **`renderTicks`** _(Component | Function(`message`))_ - Custom ticks indicator to display message status
396
260
  - **`onPressMessage`** _(Function(`context`, `message`))_ - Callback when a message bubble is pressed
397
- - **`onLongPressMessage`** _(Function(`context`, `message`))_ - Callback when a message bubble is long-pressed (see [example using `showActionSheetWithOptions()`](https://github.com/FaridSafi/react-native-gifted-chat/blob/master@%7B2017-09-25%7D/src/Bubble.js#L96-L119))
398
- - **`inverted`** _(Bool)_ - Reverses display order of `messages`; default is `true`
399
- - **`renderUsernameOnMessage`** _(Bool)_ - Indicate whether to show the user's username inside the message bubble; default is `false`
400
- - **`renderUsername`** _(Function)_ - Custom Username container
401
- - **`renderMessage`** _(Function)_ - Custom message container
402
- - **`renderMessageText`** _(Function)_ - Custom message text
403
- - **`renderMessageImage`** _(Function)_ - Custom message image
404
- - **`renderMessageVideo`** _(Function)_ - Custom message video
405
- - **`renderMessageAudio`** _(Function)_ - Custom message audio
261
+ - **`onLongPressMessage`** _(Function(`context`, `message`))_ - Callback when a message bubble is long-pressed; you can use this to show action sheets (e.g., copy, delete, reply)
406
262
  - **`imageProps`** _(Object)_ - Extra props to be passed to the [`<Image>`](https://reactnative.dev/docs/image.html) component created by the default `renderMessageImage`
407
263
  - **`imageStyle`** _(Object)_ - Custom style for message images
408
264
  - **`videoProps`** _(Object)_ - Extra props to be passed to the video component created by the required `renderMessageVideo`
409
- - **`isCustomViewBottom`** _(Bool)_ - Determine whether renderCustomView is displayed before or after the text, image and video views; default is `false`
410
- - **`renderCustomView`** _(Function)_ - Custom view inside the bubble
411
- - **`renderDay`** _(Function)_ - Custom day above a message
412
- - **`renderTime`** _(Function)_ - Custom time inside a message
413
- - **`timeTextStyle`** _(Object)_ - Custom text style for time inside messages (supports left/right styles)
414
- - **`renderFooter`** _(Function)_ - Custom footer component on the ListView, e.g. `'User is typing...'`; see [App.tsx](/example/App.tsx) for an example. Overrides default typing indicator that triggers when `isTyping` is true.
415
- - **`renderTypingIndicator`** _(Function)_ - Custom typing indicator component
416
- - **`renderChatEmpty`** _(Function)_ - Custom component to render in the ListView when messages are empty
417
- - **`renderChatFooter`** _(Function)_ - Custom component to render below the MessageContainer (separate from the ListView)
418
- - **`renderInputToolbar`** _(Function)_ - Custom message composer container
419
- - **`renderComposer`** _(Function)_ - Custom text input message composer
420
- - **`renderActions`** _(Function)_ - Custom action button on the left of the message composer
421
- - **`renderSend`** _(Function)_ - Custom send button; you can pass children to the original `Send` component quite easily, for example, to use a custom icon ([example](https://github.com/FaridSafi/react-native-gifted-chat/pull/487))
422
- - **`renderAccessory`** _(Function)_ - Custom second line of actions below the message composer
423
- - **`onPressActionButton`** _(Function)_ - Callback when the Action button is pressed (if set, the default `actionSheet` will not be used)
424
- - **`actionSheet`** _(Function)_ - Custom action sheet interface for showing action options
425
- - **`actions`** _(Array)_ - Custom action options for the input toolbar action button; array of objects with `title` (string) and `action` (function) properties
426
- - **`actionSheetOptionTintColor`** _(String)_ - Tint color for action sheet options
427
- - **`focusOnInputWhenOpeningKeyboard`** _(Bool)_ - Focus on <TextInput> automatically when opening the keyboard; default `true`
428
- - **`minInputToolbarHeight`** _(Integer)_ - Minimum height of the input toolbar; default is `44`
429
- - **`listProps`** _(Object)_ - Extra props to be passed to the messages [`<FlatList>`](https://reactnative.dev/docs/flatlist.html); some props can't be overridden, see the code in `MessageContainer.render()` for details
430
- - **`textInputProps`** _(Object)_ - props to be passed to the [`<TextInput>`](https://reactnative.dev/docs/textinput.html).
431
265
  - **`messageTextProps`** _(Object)_ - Extra props to be passed to the MessageText component. Useful for customizing link parsing behavior, text styles, and matchers. Supports all [react-native-autolink](https://github.com/joshswan/react-native-autolink) props including:
432
266
  - `matchers` - Custom matchers for linking message content (like URLs, phone numbers, hashtags, mentions)
433
267
  - `linkStyle` - Custom style for links
@@ -437,63 +271,121 @@ interface QuickReplies {
437
271
 
438
272
  Example:
439
273
 
440
- ```js
274
+ ```tsx
441
275
  <GiftedChat
442
276
  messageTextProps={{
277
+ phone: false, // Disable default phone number linking
443
278
  matchers: [
444
279
  {
445
- pattern: /#(\w+)/g,
446
- style: { color: '#0084ff', fontWeight: 'bold' },
447
- onPress: (match) => console.log('Hashtag:', match.getAnchorText()),
448
- },
449
- {
450
- pattern: /(?<![\.\w])@(?!__ELEMENT-)([\w-]+)/g,
451
- style: { color: '#0084ff', fontWeight: 'bold' },
452
- onPress: (match) => console.log('Mention:', match.getAnchorText()),
280
+ type: 'phone',
281
+ pattern: /\+?[1-9][0-9\-\(\) ]{7,}[0-9]/g,
282
+ getLinkUrl: (replacerArgs: ReplacerArgs): string => {
283
+ return replacerArgs[0].replace(/[\-\(\) ]/g, '')
284
+ },
285
+ getLinkText: (replacerArgs: ReplacerArgs): string => {
286
+ return replacerArgs[0]
287
+ },
288
+ style: styles.linkStyle,
289
+ onPress: (match: CustomMatch) => {
290
+ const url = match.getAnchorHref()
291
+
292
+ const options: {
293
+ title: string
294
+ action?: () => void
295
+ }[] = [
296
+ { title: 'Copy', action: () => setStringAsync(url) },
297
+ { title: 'Call', action: () => Linking.openURL(`tel:${url}`) },
298
+ { title: 'Send SMS', action: () => Linking.openURL(`sms:${url}`) },
299
+ { title: 'Cancel' },
300
+ ]
301
+
302
+ showActionSheetWithOptions({
303
+ options: options.map(o => o.title),
304
+ cancelButtonIndex: options.length - 1,
305
+ }, (buttonIndex?: number) => {
306
+ if (buttonIndex === undefined)
307
+ return
308
+
309
+ const option = options[buttonIndex]
310
+ option.action?.()
311
+ })
312
+ },
453
313
  },
454
314
  ],
455
315
  linkStyle: { left: { color: 'blue' }, right: { color: 'lightblue' } },
456
- phone: false,
457
316
  }}
458
317
  />
459
318
  ```
460
319
 
461
- - **`matchers`** _(Array)_ - **Deprecated:** Use `messageTextProps.matchers` instead. Custom matchers for [react-native-autolink](https://github.com/joshswan/react-native-autolink) used to linking message content (like URLs and phone numbers).
320
+ See full example in [LinksExample](example/components/chat-examples/LinksExample.tsx)
462
321
 
463
- - **`extraData`** _(Object)_ - Extra props for re-rendering FlatList on demand. This will be useful for rendering footer etc.
464
- - **`minComposerHeight`** _(Object)_ - Custom min-height of the composer.
465
- - **`maxComposerHeight`** _(Object)_ - Custom max height of the composer.
322
+ ### Avatars
323
+
324
+ - **`renderAvatar`** _(Component | Function)_ - Custom message avatar; set to `null` to not render any avatar for the message
325
+ - **`isUserAvatarVisible`** _(Bool)_ - Whether to render an avatar for the current user; default is `false`, only show avatars for other users
326
+ - **`isAvatarVisibleForEveryMessage`** _(Bool)_ - When false, avatars will only be displayed when a consecutive message is from the same user on the same day; default is `false`
327
+ - **`onPressAvatar`** _(Function(`user`))_ - Callback when a message avatar is tapped
328
+ - **`onLongPressAvatar`** _(Function(`user`))_ - Callback when a message avatar is long-pressed
329
+ - **`isAvatarOnTop`** _(Bool)_ - Render the message avatar at the top of consecutive messages, rather than the bottom; default is `false`
466
330
 
467
- * **`isScrollToBottomEnabled`** _(Bool)_ - Enables the scroll to bottom Component (Default is false)
468
- * **`scrollToBottomComponent`** _(Function)_ - Custom Scroll To Bottom Component container
469
- * **`scrollToBottomOffset`** _(Integer)_ - Custom Height Offset upon which to begin showing Scroll To Bottom Component (Default is 200)
470
- * **`scrollToBottomStyle`** _(Object)_ - Custom style for Bottom Component container
471
- * **`alignTop`** _(Boolean)_ Controls whether or not the message bubbles appear at the top of the chat (Default is false - bubbles align to bottom)
472
- * **`onQuickReply`** _(Function)_ - Callback when sending a quick reply (to backend server)
473
- * **`renderQuickReplies`** _(Function)_ - Custom all quick reply view
474
- * **`quickReplyStyle`** _(StyleProp<ViewStyle>)_ - Custom quick reply view style
475
- * **`quickReplyTextStyle`** _(StyleProp<TextStyle>)_ - Custom text style for quick reply buttons
476
- * **`quickReplyContainerStyle`** _(StyleProp<ViewStyle>)_ - Custom container style for quick replies
477
- * **`renderQuickReplySend`** _(Function)_ - Custom quick reply **send** view
478
- * **`shouldUpdateMessage`** _(Function)_ - Lets the message component know when to update outside of normal cases.
479
- * **`typingIndicatorStyle`** _(StyleProp<ViewStyle>)_ - Custom style for the TypingIndicator component.
480
- * **`handleOnScroll`** _(Function)_ - Custom scroll event handler for the message list
481
-
482
- ## Notes for [Redux](https://github.com/reactjs/redux)
483
-
484
- The `messages` prop should work out-of-the-box with Redux. In most cases, this is all you need.
485
-
486
- If you decide to specify a `text` prop, GiftedChat will no longer manage its own internal `text` state and will defer entirely to your prop.
487
- This is great for using a tool like Redux, but there's one extra step you'll need to take:
488
- simply implement `onInputTextChanged` to receive typing events and reset events (e.g. to clear the text `onSend`):
331
+ ### Username
489
332
 
490
- ```js
491
- <GiftedChat
492
- text={customText}
493
- onInputTextChanged={text => this.setCustomText(text)}
494
- /* ... */
495
- />
496
- ```
333
+ - **`isUsernameVisible`** _(Bool)_ - Indicate whether to show the user's username inside the message bubble; default is `false`
334
+ - **`renderUsername`** _(Component | Function)_ - Custom Username container
335
+
336
+ ### Date & Time
337
+
338
+ - **`timeFormat`** _(String)_ - Format to use for rendering times; default is `'LT'` (see [Day.js Format](https://day.js.org/docs/en/display/format))
339
+ - **`dateFormat`** _(String)_ - Format to use for rendering dates; default is `'D MMMM'` (see [Day.js Format](https://day.js.org/docs/en/display/format))
340
+ - **`dateFormatCalendar`** _(Object)_ - Format to use for rendering relative times; default is `{ sameDay: '[Today]' }` (see [Day.js Calendar](https://day.js.org/docs/en/plugin/calendar))
341
+ - **`renderDay`** _(Component | Function)_ - Custom day above a message
342
+ - **`renderTime`** _(Component | Function)_ - Custom time inside a message
343
+ - **`timeTextStyle`** _(Object)_ - Custom text style for time inside messages (supports left/right styles)
344
+
345
+ ### System Messages
346
+
347
+ - **`renderSystemMessage`** _(Component | Function)_ - Custom system message
348
+
349
+ ### Load Earlier Messages
350
+
351
+ - **`loadEarlierMessagesProps`** _(Object)_ - Props to pass to the LoadEarlierMessages component. The button is only visible when `isAvailable` is `true`. Supports the following props:
352
+ - `isAvailable` - Controls button visibility (default: false)
353
+ - `onPress` - Callback when button is pressed
354
+ - `isLoading` - Display loading indicator (default: false)
355
+ - `isInfiniteScrollEnabled` - Enable infinite scroll up when reaching the top of messages container, automatically calls `onPress` (not yet supported for web)
356
+ - `label` - Override the default "Load earlier messages" text
357
+ - `containerStyle` - Custom style for the button container
358
+ - `wrapperStyle` - Custom style for the button wrapper
359
+ - `textStyle` - Custom style for the button text
360
+ - `activityIndicatorStyle` - Custom style for the loading indicator
361
+ - `activityIndicatorColor` - Color of the loading indicator (default: 'white')
362
+ - `activityIndicatorSize` - Size of the loading indicator (default: 'small')
363
+ - **`renderLoadEarlier`** _(Component | Function)_ - Custom "Load earlier messages" button
364
+
365
+ ### Typing Indicator
366
+
367
+ - **`isTyping`** _(Bool)_ - Typing Indicator state; default `false`. If you use`renderFooter` it will override this.
368
+ - **`renderTypingIndicator`** _(Component | Function)_ - Custom typing indicator component
369
+ - **`typingIndicatorStyle`** _(StyleProp<ViewStyle>)_ - Custom style for the TypingIndicator component.
370
+ - **`renderFooter`** _(Component | Function)_ - Custom footer component on the ListView, e.g. `'User is typing...'`; see [CustomizedFeaturesExample.tsx](example/components/chat-examples/CustomizedFeaturesExample.tsx) for an example. Overrides default typing indicator that triggers when `isTyping` is true.
371
+
372
+ ### Quick Replies
373
+
374
+ See [Quick Replies example in messages.ts](example/example-expo/data/messages.ts)
375
+
376
+ - **`onQuickReply`** _(Function)_ - Callback when sending a quick reply (to backend server)
377
+ - **`renderQuickReplies`** _(Function)_ - Custom all quick reply view
378
+ - **`quickReplyStyle`** _(StyleProp<ViewStyle>)_ - Custom quick reply view style
379
+ - **`quickReplyTextStyle`** _(StyleProp<TextStyle>)_ - Custom text style for quick reply buttons
380
+ - **`quickReplyContainerStyle`** _(StyleProp<ViewStyle>)_ - Custom container style for quick replies
381
+ - **`renderQuickReplySend`** _(Function)_ - Custom quick reply **send** view
382
+
383
+ ### Scroll to Bottom
384
+
385
+ - **`isScrollToBottomEnabled`** _(Bool)_ - Enables the scroll to bottom Component (Default is false)
386
+ - **`scrollToBottomComponent`** _(Function)_ - Custom Scroll To Bottom Component container
387
+ - **`scrollToBottomOffset`** _(Integer)_ - Custom Height Offset upon which to begin showing Scroll To Bottom Component (Default is 200)
388
+ - **`scrollToBottomStyle`** _(Object)_ - Custom style for Bottom Component container
497
389
 
498
390
  ## Notes for Android
499
391
 
@@ -578,6 +470,26 @@ module.exports = function override(config, env) {
578
470
 
579
471
  > Another example with **Gatsby** : [xcarpentier/clean-archi-boilerplate](https://github.com/xcarpentier/clean-archi-boilerplate/tree/develop/apps/web)
580
472
 
473
+ ## Testing
474
+ `TEST_ID` is exported as constants that can be used in your testing library of choice
475
+
476
+ Gifted Chat uses `onLayout` to determine the height of the chat container. To trigger `onLayout` during your tests, you can run the following bits of code.
477
+
478
+ ```typescript
479
+ const WIDTH = 200; // or any number
480
+ const HEIGHT = 2000; // or any number
481
+
482
+ const loadingWrapper = getByTestId(TEST_ID.LOADING_WRAPPER)
483
+ fireEvent(loadingWrapper, 'layout', {
484
+ nativeEvent: {
485
+ layout: {
486
+ width: WIDTH,
487
+ height: HEIGHT,
488
+ },
489
+ },
490
+ })
491
+ ```
492
+
581
493
  ## Questions
582
494
 
583
495
  - [How can I set Bubble color for each user?](https://github.com/FaridSafi/react-native-gifted-chat/issues/672)
@@ -590,6 +502,13 @@ module.exports = function override(config, env) {
590
502
  - [How to use renderLoading?](https://github.com/FaridSafi/react-native-gifted-chat/issues/298)
591
503
  - [Can I use MySql to save the message?](https://github.com/FaridSafi/react-native-gifted-chat/issues/738)
592
504
 
505
+ ## You have a question?
506
+
507
+ 1. Please check this readme and you might find a response
508
+ 1. Please ask on StackOverflow first: https://stackoverflow.com/questions/tagged/react-native-gifted-chat
509
+ 1. Find responses in existing issues
510
+ 1. Try to keep issues for issues
511
+
593
512
  ## License
594
513
 
595
514
  - [MIT](LICENSE)
@@ -609,4 +528,6 @@ Feel free to ask me questions on Twitter [@FaridSafi](https://www.twitter.com/Fa
609
528
 
610
529
  ## Hire an expert!
611
530
 
612
- Looking for a ReactNative freelance expert with more than 14 years of experience? Contact Xavier from his [website](https://xaviercarpentier.com)!
531
+ Looking for a React Native freelance expert with more than 14 years of experience? Contact Xavier from his [website](https://xaviercarpentier.com)!
532
+
533
+ Need expert help with React Native Gifted Chat? Reach out to [Kesha Antonov](mailto:innokenty.longway@gmail.com)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-gifted-chat",
3
- "version": "2.8.2-alpha.6",
3
+ "version": "3.0.0-alpha.0",
4
4
  "description": "The most complete chat UI for React Native",
5
5
  "keywords": [
6
6
  "android",
@@ -80,6 +80,7 @@
80
80
  "@typescript-eslint/parser": "^8.46.4",
81
81
  "babel-jest": "^29.7.0",
82
82
  "eslint": "^9.18.0",
83
+ "eslint-import-resolver-typescript": "^4.4.4",
83
84
  "eslint-plugin-import": "^2.32.0",
84
85
  "eslint-plugin-jest": "^28.11.0",
85
86
  "eslint-plugin-perfectionist": "^4.15.1",
package/src/Actions.tsx CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  ViewStyle,
8
8
  TextStyle,
9
9
  } from 'react-native'
10
- import Color from './Color'
10
+ import { Color } from './Color'
11
11
  import { TouchableOpacity } from './components/TouchableOpacity'
12
12
  import { useChatContext } from './GiftedChatContext'
13
13
 
package/src/Avatar.tsx CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  ViewStyle,
8
8
  } from 'react-native'
9
9
  import { GiftedAvatar } from './GiftedAvatar'
10
- import { IMessage, LeftRightStyle, User } from './types'
10
+ import { IMessage, LeftRightStyle, User } from './Models'
11
11
  import { isSameUser, isSameDay } from './utils'
12
12
 
13
13
  interface Styles {
@@ -57,8 +57,8 @@ export interface AvatarProps<TMessage extends IMessage> {
57
57
  previousMessage?: TMessage
58
58
  nextMessage?: TMessage
59
59
  position: 'left' | 'right'
60
- renderAvatarOnTop?: boolean
61
- showAvatarForEveryMessage?: boolean
60
+ isAvatarOnTop?: boolean
61
+ isAvatarVisibleForEveryMessage?: boolean
62
62
  imageStyle?: LeftRightStyle<ImageStyle>
63
63
  containerStyle?: LeftRightStyle<ViewStyle>
64
64
  textStyle?: TextStyle
@@ -71,8 +71,8 @@ export function Avatar<TMessage extends IMessage = IMessage> (
71
71
  props: AvatarProps<TMessage>
72
72
  ) {
73
73
  const {
74
- renderAvatarOnTop,
75
- showAvatarForEveryMessage,
74
+ isAvatarOnTop,
75
+ isAvatarVisibleForEveryMessage,
76
76
  containerStyle,
77
77
  position,
78
78
  currentMessage,
@@ -84,13 +84,13 @@ export function Avatar<TMessage extends IMessage = IMessage> (
84
84
  onLongPressAvatar,
85
85
  } = props
86
86
 
87
- const messageToCompare = renderAvatarOnTop ? previousMessage : nextMessage
87
+ const messageToCompare = isAvatarOnTop ? previousMessage : nextMessage
88
88
 
89
89
  const renderAvatarComponent = useCallback(() => {
90
90
  if (renderAvatar)
91
91
  return renderAvatar({
92
- renderAvatarOnTop,
93
- showAvatarForEveryMessage,
92
+ isAvatarOnTop,
93
+ isAvatarVisibleForEveryMessage,
94
94
  containerStyle,
95
95
  position,
96
96
  currentMessage,
@@ -117,8 +117,8 @@ export function Avatar<TMessage extends IMessage = IMessage> (
117
117
  return null
118
118
  }, [
119
119
  renderAvatar,
120
- renderAvatarOnTop,
121
- showAvatarForEveryMessage,
120
+ isAvatarOnTop,
121
+ isAvatarVisibleForEveryMessage,
122
122
  containerStyle,
123
123
  position,
124
124
  currentMessage,
@@ -133,7 +133,7 @@ export function Avatar<TMessage extends IMessage = IMessage> (
133
133
  return null
134
134
 
135
135
  if (
136
- !showAvatarForEveryMessage &&
136
+ !isAvatarVisibleForEveryMessage &&
137
137
  currentMessage &&
138
138
  messageToCompare &&
139
139
  isSameUser(currentMessage, messageToCompare) &&
@@ -159,7 +159,7 @@ export function Avatar<TMessage extends IMessage = IMessage> (
159
159
  <View
160
160
  style={[
161
161
  styles[position].container,
162
- renderAvatarOnTop && styles[position].onTop,
162
+ isAvatarOnTop && styles[position].onTop,
163
163
  containerStyle?.[position],
164
164
  ]}
165
165
  >