react-native-gifted-chat 2.9.0-alpha.0 → 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.
- package/README.md +183 -262
- package/package.json +1 -1
- package/src/Avatar.tsx +12 -12
- package/src/Bubble/index.tsx +2 -2
- package/src/Bubble/types.ts +22 -22
- package/src/Composer.tsx +0 -3
- package/src/GiftedAvatar.tsx +1 -1
- package/src/GiftedChat/index.tsx +20 -23
- package/src/GiftedChat/types.ts +38 -47
- package/src/InputToolbar.tsx +6 -6
- package/src/Message/index.tsx +5 -6
- package/src/Message/types.ts +8 -12
- package/src/MessageContainer/components/DayAnimated/types.ts +1 -1
- package/src/MessageContainer/components/Item/index.tsx +2 -2
- package/src/MessageContainer/components/Item/types.ts +1 -1
- package/src/MessageContainer/index.tsx +28 -30
- package/src/MessageContainer/types.ts +12 -16
- package/src/MessageImage.tsx +1 -1
- package/src/MessageText.tsx +1 -1
- package/src/Models.ts +63 -0
- package/src/QuickReplies.tsx +1 -1
- package/src/Send.tsx +30 -31
- package/src/SystemMessage.tsx +1 -1
- package/src/Time.tsx +1 -1
- package/src/__tests__/Message.test.tsx +2 -2
- package/src/__tests__/Send.test.tsx +1 -1
- package/src/__tests__/__snapshots__/Actions.test.tsx.snap +2 -86
- package/src/__tests__/__snapshots__/LoadEarlier.test.tsx.snap +3 -89
- package/src/__tests__/__snapshots__/Message.test.tsx.snap +2 -2
- package/src/__tests__/__snapshots__/Send.test.tsx.snap +10 -142
- package/src/__tests__/data.ts +1 -1
- package/src/components/TouchableOpacity.tsx +19 -8
- package/src/types.ts +1 -63
- package/src/utils.ts +1 -1
package/README.md
CHANGED
|
@@ -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
|
-
##
|
|
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
|
-
##
|
|
188
|
+
## Different examples
|
|
216
189
|
|
|
217
|
-
|
|
190
|
+
Check out code of [`examples`](example)
|
|
218
191
|
|
|
219
|
-
##
|
|
192
|
+
## Data structure
|
|
220
193
|
|
|
221
|
-
|
|
194
|
+
Messages, system messages, quick replies etc.: [data structure](src/Models.ts)
|
|
222
195
|
|
|
223
|
-
##
|
|
196
|
+
## Props
|
|
224
197
|
|
|
225
|
-
|
|
198
|
+
### Core Configuration
|
|
226
199
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
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
|
-
|
|
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
|
-
|
|
208
|
+
- **`messageContainerRef`** _(FlatList ref)_ - Ref to the flatlist
|
|
209
|
+
- **`textInputRef`** _(TextInput ref)_ - Ref to the text input
|
|
268
210
|
|
|
269
|
-
|
|
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
|
-
|
|
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
|
-
|
|
219
|
+
### Text Input & Composer
|
|
282
220
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
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
|
-
|
|
291
|
-
type: 'radio' | 'checkbox'
|
|
292
|
-
values: Reply[]
|
|
293
|
-
keepIt?: boolean
|
|
294
|
-
}
|
|
295
|
-
```
|
|
234
|
+
### Actions & Action Sheet
|
|
296
235
|
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
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
|
-
|
|
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
|
-
- **`
|
|
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')
|
|
244
|
+
- **`renderMessage`** _(Component | Function)_ - Custom message container
|
|
385
245
|
- **`renderLoading`** _(Component | Function)_ - Render a loading view when initializing
|
|
386
|
-
- **`
|
|
387
|
-
- **`
|
|
388
|
-
- **`
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
- **`renderAvatarOnTop`** _(Bool)_ - Render the message avatar at the top of consecutive messages, rather than the bottom; default is `false`
|
|
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
|
+
|
|
393
252
|
- **`renderBubble`** _(Component | Function)_ - Custom message bubble
|
|
394
|
-
- **`renderTicks`** _(Component | Function(`message`))_ - Custom ticks indicator to display message status
|
|
395
|
-
- **`renderSystemMessage`** _(Component | Function)_ - Custom system message
|
|
396
|
-
- **`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`** _(Component | Function)_ - Custom Username container
|
|
401
|
-
- **`renderMessage`** _(Component | Function)_ - Custom message container
|
|
402
253
|
- **`renderMessageText`** _(Component | Function)_ - Custom message text
|
|
403
254
|
- **`renderMessageImage`** _(Component | Function)_ - Custom message image
|
|
404
255
|
- **`renderMessageVideo`** _(Component | Function)_ - Custom message video
|
|
405
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
|
|
260
|
+
- **`onPressMessage`** _(Function(`context`, `message`))_ - Callback when a message bubble is pressed
|
|
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`** _(Component | Function)_ - Custom view inside the bubble
|
|
411
|
-
- **`renderDay`** _(Component | Function)_ - Custom day above a message
|
|
412
|
-
- **`renderTime`** _(Component | Function)_ - Custom time inside a message
|
|
413
|
-
- **`timeTextStyle`** _(Object)_ - Custom text style for time inside messages (supports left/right styles)
|
|
414
|
-
- **`renderFooter`** _(Component | 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`** _(Component | Function)_ - Custom typing indicator component
|
|
416
|
-
- **`renderChatEmpty`** _(Component | Function)_ - Custom component to render in the ListView when messages are empty
|
|
417
|
-
- **`renderChatFooter`** _(Component | Function)_ - Custom component to render below the MessageContainer (separate from the ListView)
|
|
418
|
-
- **`renderInputToolbar`** _(Component | Function)_ - Custom message composer container
|
|
419
|
-
- **`renderComposer`** _(Component | Function)_ - Custom text input message composer
|
|
420
|
-
- **`renderActions`** _(Component | Function)_ - Custom action button on the left of the message composer
|
|
421
|
-
- **`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))
|
|
422
|
-
- **`renderAccessory`** _(Component | 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
|
-
```
|
|
274
|
+
```tsx
|
|
441
275
|
<GiftedChat
|
|
442
276
|
messageTextProps={{
|
|
277
|
+
phone: false, // Disable default phone number linking
|
|
443
278
|
matchers: [
|
|
444
279
|
{
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
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
|
-
|
|
320
|
+
See full example in [LinksExample](example/components/chat-examples/LinksExample.tsx)
|
|
462
321
|
|
|
463
|
-
|
|
464
|
-
- **`minComposerHeight`** _(Object)_ - Custom min-height of the composer.
|
|
465
|
-
- **`maxComposerHeight`** _(Object)_ - Custom max height of the composer.
|
|
322
|
+
### Avatars
|
|
466
323
|
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
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`):
|
|
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`
|
|
489
330
|
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
331
|
+
### Username
|
|
332
|
+
|
|
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
|
|
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
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 './
|
|
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
|
-
|
|
61
|
-
|
|
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
|
-
|
|
75
|
-
|
|
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 =
|
|
87
|
+
const messageToCompare = isAvatarOnTop ? previousMessage : nextMessage
|
|
88
88
|
|
|
89
89
|
const renderAvatarComponent = useCallback(() => {
|
|
90
90
|
if (renderAvatar)
|
|
91
91
|
return renderAvatar({
|
|
92
|
-
|
|
93
|
-
|
|
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
|
-
|
|
121
|
-
|
|
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
|
-
!
|
|
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
|
-
|
|
162
|
+
isAvatarOnTop && styles[position].onTop,
|
|
163
163
|
containerStyle?.[position],
|
|
164
164
|
]}
|
|
165
165
|
>
|
package/src/Bubble/index.tsx
CHANGED
|
@@ -10,11 +10,11 @@ import { MessageAudio } from '../MessageAudio'
|
|
|
10
10
|
import { MessageImage } from '../MessageImage'
|
|
11
11
|
import { MessageText } from '../MessageText'
|
|
12
12
|
import { MessageVideo } from '../MessageVideo'
|
|
13
|
+
import { IMessage } from '../Models'
|
|
13
14
|
import { QuickReplies } from '../QuickReplies'
|
|
14
15
|
import stylesCommon from '../styles'
|
|
15
16
|
|
|
16
17
|
import { Time } from '../Time'
|
|
17
|
-
import { IMessage } from '../types'
|
|
18
18
|
import { isSameUser, isSameDay, renderComponentOrElement } from '../utils'
|
|
19
19
|
|
|
20
20
|
import styles from './styles'
|
|
@@ -284,7 +284,7 @@ export const Bubble = <TMessage extends IMessage = IMessage>(props: BubbleProps<
|
|
|
284
284
|
renderUsername,
|
|
285
285
|
} = props
|
|
286
286
|
|
|
287
|
-
if (props.
|
|
287
|
+
if (props.isUsernameVisible && currentMessage) {
|
|
288
288
|
if (user && currentMessage.user._id === user._id)
|
|
289
289
|
return null
|
|
290
290
|
|