react-native-gifted-chat 3.2.2 â 3.3.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 +450 -156
- package/package.json +9 -8
- package/src/Bubble/index.tsx +34 -2
- package/src/Bubble/types.ts +17 -4
- package/src/Composer.tsx +1 -2
- package/src/Day/index.tsx +2 -2
- package/src/Day/types.ts +3 -2
- package/src/GiftedAvatar.tsx +1 -1
- package/src/GiftedChat/index.tsx +109 -23
- package/src/GiftedChat/types.ts +9 -3
- package/src/InputToolbar.tsx +62 -8
- package/src/Message/index.tsx +181 -21
- package/src/Message/types.ts +4 -0
- package/src/MessageReply.tsx +160 -0
- package/src/MessageText.tsx +2 -2
- package/src/MessagesContainer/components/DayAnimated/index.tsx +5 -1
- package/src/MessagesContainer/components/Item/index.tsx +82 -47
- package/src/MessagesContainer/index.tsx +30 -19
- package/src/MessagesContainer/styles.ts +2 -0
- package/src/MessagesContainer/types.ts +30 -3
- package/src/Models.ts +3 -0
- package/src/Reply/index.ts +1 -0
- package/src/Reply/types.ts +80 -0
- package/src/ReplyPreview.tsx +132 -0
- package/src/Send.tsx +8 -3
- package/src/SystemMessage.tsx +22 -16
- package/src/__tests__/MessageReply.test.tsx +54 -0
- package/src/__tests__/ReplyPreview.test.tsx +41 -0
- package/src/__tests__/__snapshots__/GiftedChat.test.tsx.snap +69 -42
- package/src/__tests__/__snapshots__/InputToolbar.test.tsx.snap +11 -15
- package/src/__tests__/__snapshots__/MessageImage.test.tsx.snap +24 -18
- package/src/__tests__/__snapshots__/MessageReply.test.tsx.snap +181 -0
- package/src/__tests__/__snapshots__/ReplyPreview.test.tsx.snap +403 -0
- package/src/__tests__/__snapshots__/Send.test.tsx.snap +3 -0
- package/src/__tests__/__snapshots__/SystemMessage.test.tsx.snap +36 -25
- package/src/components/MessageReply.tsx +156 -0
- package/src/components/ReplyPreview.tsx +230 -0
- package/src/index.ts +6 -1
- package/src/types.ts +17 -16
- package/src/utils.ts +11 -3
- package/CHANGELOG.md +0 -364
- package/src/reanimatedCompat.ts +0 -27
package/README.md
CHANGED
|
@@ -1,33 +1,45 @@
|
|
|
1
|
-
<h3 align="center">
|
|
2
|
-
đŦ Gifted Chat
|
|
3
|
-
</h3>
|
|
4
1
|
<p align="center">
|
|
5
|
-
The most complete chat UI for React Native & Web
|
|
6
|
-
</p>
|
|
7
|
-
<p align="center">
|
|
8
|
-
<a href="https://www.npmjs.com/package/react-native-gifted-chat">
|
|
9
|
-
<img alt="npm downloads" src="https://img.shields.io/npm/dm/react-native-gifted-chat.svg"/></a>
|
|
10
2
|
<a href="https://www.npmjs.com/package/react-native-gifted-chat"><img alt="npm version" src="https://badge.fury.io/js/react-native-gifted-chat.svg"/></a>
|
|
11
|
-
|
|
3
|
+
<a href="https://www.npmjs.com/package/react-native-gifted-chat"><img alt="npm downloads" src="https://img.shields.io/npm/dm/react-native-gifted-chat.svg"/></a>
|
|
4
|
+
<a href="https://circleci.com/gh/FaridSafi/react-native-gifted-chat"><img src="https://circleci.com/gh/FaridSafi/react-native-gifted-chat.svg?style=shield" alt="build"></a>
|
|
5
|
+
<img src="https://img.shields.io/badge/platforms-iOS%20%7C%20Android%20%7C%20Web-lightgrey.svg" alt="platforms">
|
|
6
|
+
<img src="https://img.shields.io/badge/TypeScript-supported-blue.svg" alt="TypeScript">
|
|
7
|
+
<img src="https://img.shields.io/badge/Expo-compatible-000020.svg" alt="Expo compatible">
|
|
12
8
|
</p>
|
|
13
9
|
|
|
14
|
-
|
|
10
|
+
<h1 align="center">React Native Gifted Chat</h1>
|
|
15
11
|
|
|
16
|
-
<h3 align="center">
|
|
17
|
-
đ Try it now in your browser!
|
|
18
|
-
</h3>
|
|
19
12
|
<p align="center">
|
|
20
|
-
|
|
21
|
-
<img src="https://img.shields.io/badge/âļī¸_Try_GiftedChat_Playground-4630EB?style=for-the-badge&logo=expo&logoColor=white" alt="Try GiftedChat on Expo Snack"/>
|
|
22
|
-
</a>
|
|
13
|
+
The most complete chat UI for React Native & Web
|
|
23
14
|
</p>
|
|
15
|
+
|
|
24
16
|
<p align="center">
|
|
25
|
-
<
|
|
17
|
+
<a href="https://snack.expo.dev/@kesha-antonov/gifted-chat-playground" target="_blank">
|
|
18
|
+
<img src="https://img.shields.io/badge/âļī¸_Try_in_Browser-4630EB?style=for-the-badge&logo=expo&logoColor=white" alt="Try GiftedChat on Expo Snack"/>
|
|
19
|
+
</a>
|
|
26
20
|
</p>
|
|
27
21
|
|
|
28
|
-
|
|
22
|
+
---
|
|
29
23
|
|
|
30
|
-
|
|
24
|
+
## ⨠Features
|
|
25
|
+
|
|
26
|
+
- đ¨ **Fully Customizable** - Override any component with your own implementation
|
|
27
|
+
- đ **Composer Actions** - Attach photos, files, or trigger custom actions
|
|
28
|
+
- âŠī¸ **Reply to Messages** - Swipe-to-reply with reply preview and message threading
|
|
29
|
+
- âŽī¸ **Load Earlier Messages** - Infinite scroll with pagination support
|
|
30
|
+
- đ **Copy to Clipboard** - Long-press messages to copy text
|
|
31
|
+
- đ **Smart Link Parsing** - Auto-detect URLs, emails, phone numbers, hashtags, mentions
|
|
32
|
+
- đ¤ **Avatars** - User initials or custom avatar images
|
|
33
|
+
- đ **Localized Dates** - Full i18n support via Day.js
|
|
34
|
+
- â¨ī¸ **Keyboard Handling** - Smart keyboard avoidance for all platforms
|
|
35
|
+
- đŦ **System Messages** - Display system notifications in chat
|
|
36
|
+
- ⥠**Quick Replies** - Bot-style quick reply buttons
|
|
37
|
+
- âī¸ **Typing Indicator** - Show when users are typing
|
|
38
|
+
- â
**Message Status** - Tick indicators for sent/delivered/read states
|
|
39
|
+
- âŦī¸ **Scroll to Bottom** - Quick navigation button
|
|
40
|
+
- đ **Web Support** - Works with react-native-web
|
|
41
|
+
- đą **Expo Support** - Easy integration with Expo projects
|
|
42
|
+
- đ **TypeScript** - Complete TypeScript definitions included
|
|
31
43
|
|
|
32
44
|
<p align="center">
|
|
33
45
|
<img width="200" src="https://github.com/user-attachments/assets/c9da88f5-0b20-471c-8cd7-373bdb767517" />
|
|
@@ -39,109 +51,72 @@
|
|
|
39
51
|
|
|
40
52
|
---
|
|
41
53
|
|
|
42
|
-
##
|
|
43
|
-
|
|
44
|
-
-
|
|
45
|
-
-
|
|
46
|
-
-
|
|
47
|
-
-
|
|
48
|
-
-
|
|
49
|
-
-
|
|
50
|
-
-
|
|
51
|
-
-
|
|
52
|
-
-
|
|
53
|
-
-
|
|
54
|
-
-
|
|
55
|
-
-
|
|
56
|
-
- Ticks indicator to display message status ( delivered, read )
|
|
57
|
-
- Scroll to bottom button
|
|
58
|
-
- react-native-web [web configuration](#react-native-web)
|
|
59
|
-
|
|
60
|
-
## Sponsor
|
|
54
|
+
## đ Table of Contents
|
|
55
|
+
|
|
56
|
+
- [Features](#-features)
|
|
57
|
+
- [Requirements](#-requirements)
|
|
58
|
+
- [Installation](#-installation)
|
|
59
|
+
- [Usage](#-usage)
|
|
60
|
+
- [Props Reference](#-props-reference)
|
|
61
|
+
- [Data Structure](#-data-structure)
|
|
62
|
+
- [Platform Notes](#-platform-notes)
|
|
63
|
+
- [Example App](#-example-app)
|
|
64
|
+
- [Troubleshooting](#-troubleshooting)
|
|
65
|
+
- [Contributing](#-contributing)
|
|
66
|
+
- [Authors](#-authors)
|
|
67
|
+
- [License](#-license)
|
|
61
68
|
|
|
62
|
-
|
|
63
|
-
<br/>
|
|
64
|
-
<a href="https://www.lereacteur.io" target="_blank">
|
|
65
|
-
<img src="https://raw.githubusercontent.com/FaridSafi/react-native-gifted-chat/master/media/logo_sponsor.png" height="60">
|
|
66
|
-
</a>
|
|
67
|
-
<br>
|
|
68
|
-
<p align="center">
|
|
69
|
-
Coding Bootcamp in Paris co-founded by Farid Safi
|
|
70
|
-
</p>
|
|
71
|
-
<a href="https://www.lereacteur.io" target="_blank">
|
|
72
|
-
<p align="center">
|
|
73
|
-
Click to learn more
|
|
74
|
-
</p>
|
|
75
|
-
</a>
|
|
76
|
-
</p>
|
|
69
|
+
---
|
|
77
70
|
|
|
78
|
-
|
|
79
|
-
<br/>
|
|
80
|
-
<a href="https://getstream.io/chat/?utm_source=Github&utm_medium=Github_Repo_Content_Ad&utm_content=Developer&utm_campaign=Github_Jan2022_Chat&utm_term=react-native-gifted-chat" target="_blank">
|
|
81
|
-
<img src="https://raw.githubusercontent.com/FaridSafi/react-native-gifted-chat/master/media/stream-logo.png" height="40">
|
|
82
|
-
</a>
|
|
83
|
-
<br>
|
|
84
|
-
<p align="center">
|
|
85
|
-
Scalable <a href="https://getstream.io/chat/?utm_source=Github&utm_medium=Github_Repo_Content_Ad&utm_content=Developer&utm_campaign=Github_Jan2022_Chat&utm_term=react-native-gifted-chat" target="_blank">chat API/Server</a> written in Go
|
|
86
|
-
</p>
|
|
87
|
-
<p align="center">
|
|
88
|
-
<a href="https://getstream.io/chat/get_started/?utm_source=Github&utm_medium=Github_Repo_Content_Ad&utm_content=Developer&utm_campaign=Github_Jan2022_Chat&utm_term=react-native-gifted-chat" target="_blank">API Tour</a> | <a href="https://dev.to/nickparsons/react-native-chat-with-chuck-norris-3h7m?utm_source=Github&utm_medium=Github_Repo_Content_Ad&utm_content=Developer&utm_campaign=Github_Jan2022_Chat&utm_term=react-native-gifted-chat" target="_blank">React Native Gifted tutorial</a>
|
|
89
|
-
</p>
|
|
90
|
-
</p>
|
|
71
|
+
## đ Requirements
|
|
91
72
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
A complete app engine featuring GiftedChat
|
|
100
|
-
</p>
|
|
101
|
-
<p align="center">
|
|
102
|
-
<a href="https://bit.ly/ethorachat" target="_blank">Check out our GitHub</a>
|
|
103
|
-
</p>
|
|
104
|
-
</p>
|
|
105
|
-
<br>
|
|
106
|
-
<p align="center">
|
|
107
|
-
<a href="https://amzn.to/3ZmTyb2" target="_blank">React Key Concepts: Consolidate your knowledge of Reactâs core features (2nd ed. Edition)</a>
|
|
108
|
-
</p>
|
|
73
|
+
| Requirement | Version |
|
|
74
|
+
|-------------|---------|
|
|
75
|
+
| React Native | >= 0.70.0 |
|
|
76
|
+
| iOS | >= 13.4 |
|
|
77
|
+
| Android | API 21+ (Android 5.0) |
|
|
78
|
+
| Expo | SDK 50+ |
|
|
79
|
+
| TypeScript | >= 5.0 (optional) |
|
|
109
80
|
|
|
110
|
-
|
|
81
|
+
---
|
|
111
82
|
|
|
112
|
-
## Installation
|
|
83
|
+
## đĻ Installation
|
|
113
84
|
|
|
114
|
-
###
|
|
85
|
+
### Expo Projects
|
|
115
86
|
|
|
116
|
-
Yarn:
|
|
117
87
|
```bash
|
|
118
|
-
|
|
88
|
+
npx expo install react-native-gifted-chat react-native-reanimated react-native-gesture-handler react-native-safe-area-context react-native-keyboard-controller
|
|
119
89
|
```
|
|
120
90
|
|
|
121
|
-
|
|
91
|
+
### Bare React Native Projects
|
|
92
|
+
|
|
93
|
+
**Step 1:** Install the packages
|
|
122
94
|
|
|
95
|
+
Using yarn:
|
|
123
96
|
```bash
|
|
124
|
-
|
|
97
|
+
yarn add react-native-gifted-chat react-native-reanimated react-native-gesture-handler react-native-safe-area-context react-native-keyboard-controller
|
|
125
98
|
```
|
|
126
99
|
|
|
127
|
-
|
|
100
|
+
Using npm:
|
|
128
101
|
```bash
|
|
129
|
-
|
|
102
|
+
npm install --save react-native-gifted-chat react-native-reanimated react-native-gesture-handler react-native-safe-area-context react-native-keyboard-controller
|
|
130
103
|
```
|
|
131
104
|
|
|
132
|
-
|
|
105
|
+
**Step 2:** Install iOS pods
|
|
133
106
|
|
|
134
107
|
```bash
|
|
135
108
|
npx pod-install
|
|
136
109
|
```
|
|
137
110
|
|
|
138
|
-
|
|
111
|
+
**Step 3:** Configure react-native-reanimated
|
|
112
|
+
|
|
113
|
+
Follow the [react-native-reanimated installation guide](https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/getting-started/#step-2-add-reanimateds-babel-plugin) to add the Babel plugin.
|
|
139
114
|
|
|
140
|
-
|
|
115
|
+
---
|
|
141
116
|
|
|
142
|
-
##
|
|
117
|
+
## đ Usage
|
|
143
118
|
|
|
144
|
-
### Basic
|
|
119
|
+
### Basic Example
|
|
145
120
|
|
|
146
121
|
```jsx
|
|
147
122
|
import React, { useState, useCallback, useEffect } from 'react'
|
|
@@ -193,15 +168,45 @@ export function Example() {
|
|
|
193
168
|
}
|
|
194
169
|
```
|
|
195
170
|
|
|
196
|
-
|
|
171
|
+
> **đĄ Tip:** Check out more examples in the [`example`](example) directory including Slack-style messages, quick replies, and custom components.
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## đ Data Structure
|
|
197
176
|
|
|
198
|
-
|
|
177
|
+
Messages, system messages, and quick replies follow the structure defined in [Models.ts](src/Models.ts).
|
|
199
178
|
|
|
200
|
-
|
|
179
|
+
<details>
|
|
180
|
+
<summary><strong>Message Object Structure</strong></summary>
|
|
201
181
|
|
|
202
|
-
|
|
182
|
+
```typescript
|
|
183
|
+
interface IMessage {
|
|
184
|
+
_id: string | number
|
|
185
|
+
text: string
|
|
186
|
+
createdAt: Date | number
|
|
187
|
+
user: User
|
|
188
|
+
image?: string
|
|
189
|
+
video?: string
|
|
190
|
+
audio?: string
|
|
191
|
+
system?: boolean
|
|
192
|
+
sent?: boolean
|
|
193
|
+
received?: boolean
|
|
194
|
+
pending?: boolean
|
|
195
|
+
quickReplies?: QuickReplies
|
|
196
|
+
}
|
|
203
197
|
|
|
204
|
-
|
|
198
|
+
interface User {
|
|
199
|
+
_id: string | number
|
|
200
|
+
name?: string
|
|
201
|
+
avatar?: string | number | (() => React.ReactNode)
|
|
202
|
+
}
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
</details>
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
## đ Props Reference
|
|
205
210
|
|
|
206
211
|
### Core Configuration
|
|
207
212
|
|
|
@@ -219,8 +224,10 @@ Messages, system messages, quick replies etc.: [data structure](src/Models.ts)
|
|
|
219
224
|
|
|
220
225
|
### Keyboard & Layout
|
|
221
226
|
|
|
222
|
-
- **`keyboardProviderProps`** _(Object)_ - Props to be passed to the [`KeyboardProvider`](https://kirillzyusko.github.io/react-native-keyboard-controller/docs/api/keyboard-provider) for keyboard handling.
|
|
223
|
-
-
|
|
227
|
+
- **`keyboardProviderProps`** _(Object)_ - Props to be passed to the [`KeyboardProvider`](https://kirillzyusko.github.io/react-native-keyboard-controller/docs/api/keyboard-provider) for keyboard handling. Default values:
|
|
228
|
+
- `statusBarTranslucent: true` - Required on Android for correct keyboard height calculation when status bar is translucent (edge-to-edge mode)
|
|
229
|
+
- `navigationBarTranslucent: true` - Required on Android for correct keyboard height calculation when navigation bar is translucent (edge-to-edge mode)
|
|
230
|
+
- **`keyboardAvoidingViewProps`** _(Object)_ - Props to be passed to the [`KeyboardAvoidingView`](https://kirillzyusko.github.io/react-native-keyboard-controller/docs/api/components/keyboard-avoiding-view). Use `keyboardVerticalOffset` to account for headers or iOS predictive text bar (~50pt).
|
|
224
231
|
- **`isAlignedTop`** _(Boolean)_ Controls whether or not the message bubbles appear at the top of the chat (Default is false - bubbles align to bottom)
|
|
225
232
|
- **`isInverted`** _(Bool)_ - Reverses display order of `messages`; default is `true`
|
|
226
233
|
|
|
@@ -229,6 +236,7 @@ Messages, system messages, quick replies etc.: [data structure](src/Models.ts)
|
|
|
229
236
|
- **`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.
|
|
230
237
|
- **`initialText`** _(String)_ - Initial text to display in the input field
|
|
231
238
|
- **`isSendButtonAlwaysVisible`** _(Bool)_ - Always show send button in input text composer; default `false`, show only when text input is not empty
|
|
239
|
+
- **`isTextOptional`** _(Bool)_ - Allow sending messages without text (useful for media-only messages); default `false`. Use with `isSendButtonAlwaysVisible` for media attachments.
|
|
232
240
|
- **`minComposerHeight`** _(Object)_ - Custom min-height of the composer.
|
|
233
241
|
- **`maxComposerHeight`** _(Object)_ - Custom max height of the composer.
|
|
234
242
|
- **`minInputToolbarHeight`** _(Integer)_ - Minimum height of the input toolbar; default is `44`
|
|
@@ -253,7 +261,7 @@ Messages, system messages, quick replies etc.: [data structure](src/Models.ts)
|
|
|
253
261
|
- **`renderLoading`** _(Component | Function)_ - Render a loading view when initializing
|
|
254
262
|
- **`renderChatEmpty`** _(Component | Function)_ - Custom component to render in the ListView when messages are empty
|
|
255
263
|
- **`renderChatFooter`** _(Component | Function)_ - Custom component to render below the MessagesContainer (separate from the ListView)
|
|
256
|
-
- **`listProps`** _(Object)_ - Extra props to be passed to the messages [`<FlatList>`](https://reactnative.dev/docs/flatlist)
|
|
264
|
+
- **`listProps`** _(Object)_ - Extra props to be passed to the messages [`<FlatList>`](https://reactnative.dev/docs/flatlist). Supports all FlatList props including `maintainVisibleContentPosition` for keeping scroll position when new messages arrive (useful for AI chatbots).
|
|
257
265
|
|
|
258
266
|
### Message Bubbles & Content
|
|
259
267
|
|
|
@@ -352,6 +360,10 @@ See full example in [LinksExample](example/components/chat-examples/LinksExample
|
|
|
352
360
|
- **`dateFormat`** _(String)_ - Format to use for rendering dates; default is `'D MMMM'` (see [Day.js Format](https://day.js.org/docs/en/display/format))
|
|
353
361
|
- **`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))
|
|
354
362
|
- **`renderDay`** _(Component | Function)_ - Custom day above a message
|
|
363
|
+
- **`dayProps`** _(Object)_ - Props to pass to the Day component:
|
|
364
|
+
- `containerStyle` - Custom style for the day container
|
|
365
|
+
- `wrapperStyle` - Custom style for the day wrapper
|
|
366
|
+
- `textProps` - Props to pass to the Text component (e.g., `style`, `allowFontScaling`, `numberOfLines`)
|
|
355
367
|
- **`renderTime`** _(Component | Function)_ - Custom time inside a message
|
|
356
368
|
- **`timeTextStyle`** _(Object)_ - Custom text style for time inside messages (supports left/right styles)
|
|
357
369
|
- **`isDayAnimationEnabled`** _(Bool)_ - Enable animated day label that appears on scroll; default is `true`
|
|
@@ -394,46 +406,214 @@ See [Quick Replies example in messages.ts](example/example-expo/data/messages.ts
|
|
|
394
406
|
- **`quickReplyContainerStyle`** _(StyleProp<ViewStyle>)_ - Custom container style for quick replies
|
|
395
407
|
- **`renderQuickReplySend`** _(Function)_ - Custom quick reply **send** view
|
|
396
408
|
|
|
409
|
+
### Reply to Messages
|
|
410
|
+
|
|
411
|
+
Gifted Chat supports swipe-to-reply functionality out of the box. When enabled, users can swipe on a message to reply to it, displaying a reply preview in the input toolbar and the replied message above the new message bubble.
|
|
412
|
+
|
|
413
|
+
> **Note:** This feature uses `ReanimatedSwipeable` from `react-native-gesture-handler` and `react-native-reanimated` for smooth, performant animations.
|
|
414
|
+
|
|
415
|
+
#### Basic Usage
|
|
416
|
+
|
|
417
|
+
```tsx
|
|
418
|
+
<GiftedChat
|
|
419
|
+
messages={messages}
|
|
420
|
+
onSend={onSend}
|
|
421
|
+
user={{ _id: 1 }}
|
|
422
|
+
reply={{
|
|
423
|
+
swipe: {
|
|
424
|
+
isEnabled: true,
|
|
425
|
+
direction: 'left', // swipe left to reply
|
|
426
|
+
},
|
|
427
|
+
}}
|
|
428
|
+
/>
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
#### Reply Props (Grouped)
|
|
432
|
+
|
|
433
|
+
The `reply` prop accepts an object with the following structure:
|
|
434
|
+
|
|
435
|
+
```typescript
|
|
436
|
+
interface ReplyProps<TMessage> {
|
|
437
|
+
// Swipe gesture configuration
|
|
438
|
+
swipe?: {
|
|
439
|
+
isEnabled?: boolean // Enable swipe-to-reply; default false
|
|
440
|
+
direction?: 'left' | 'right' // Swipe direction; default 'left'
|
|
441
|
+
onSwipe?: (message: TMessage) => void // Callback when swiped
|
|
442
|
+
renderAction?: ( // Custom swipe action component
|
|
443
|
+
progress: SharedValue<number>,
|
|
444
|
+
translation: SharedValue<number>,
|
|
445
|
+
position: 'left' | 'right'
|
|
446
|
+
) => React.ReactNode
|
|
447
|
+
actionContainerStyle?: StyleProp<ViewStyle>
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
// Reply preview styling (above input toolbar)
|
|
451
|
+
previewStyle?: {
|
|
452
|
+
containerStyle?: StyleProp<ViewStyle>
|
|
453
|
+
textStyle?: StyleProp<TextStyle>
|
|
454
|
+
imageStyle?: StyleProp<ImageStyle>
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
// In-bubble reply styling
|
|
458
|
+
messageStyle?: {
|
|
459
|
+
containerStyle?: StyleProp<ViewStyle>
|
|
460
|
+
containerStyleLeft?: StyleProp<ViewStyle>
|
|
461
|
+
containerStyleRight?: StyleProp<ViewStyle>
|
|
462
|
+
textStyle?: StyleProp<TextStyle>
|
|
463
|
+
textStyleLeft?: StyleProp<TextStyle>
|
|
464
|
+
textStyleRight?: StyleProp<TextStyle>
|
|
465
|
+
imageStyle?: StyleProp<ImageStyle>
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
// Callbacks and state
|
|
469
|
+
message?: ReplyMessage // Controlled reply state
|
|
470
|
+
onClear?: () => void // Called when reply cleared
|
|
471
|
+
onPress?: (message: TMessage) => void // Called when reply preview tapped
|
|
472
|
+
|
|
473
|
+
// Custom renderers
|
|
474
|
+
renderPreview?: (props: ReplyPreviewProps) => React.ReactNode
|
|
475
|
+
renderMessageReply?: (props: MessageReplyProps) => React.ReactNode
|
|
476
|
+
}
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
#### ReplyMessage Structure
|
|
480
|
+
|
|
481
|
+
When a message has a reply, it includes a `replyMessage` property:
|
|
482
|
+
|
|
483
|
+
```typescript
|
|
484
|
+
interface ReplyMessage {
|
|
485
|
+
_id: string | number
|
|
486
|
+
text: string
|
|
487
|
+
user: User
|
|
488
|
+
image?: string
|
|
489
|
+
audio?: string
|
|
490
|
+
}
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
#### Advanced Example with External State
|
|
494
|
+
|
|
495
|
+
```tsx
|
|
496
|
+
const [replyMessage, setReplyMessage] = useState<ReplyMessage | null>(null)
|
|
497
|
+
|
|
498
|
+
<GiftedChat
|
|
499
|
+
messages={messages}
|
|
500
|
+
onSend={messages => {
|
|
501
|
+
const newMessages = messages.map(msg => ({
|
|
502
|
+
...msg,
|
|
503
|
+
replyMessage: replyMessage || undefined,
|
|
504
|
+
}))
|
|
505
|
+
setMessages(prev => GiftedChat.append(prev, newMessages))
|
|
506
|
+
setReplyMessage(null)
|
|
507
|
+
}}
|
|
508
|
+
user={{ _id: 1 }}
|
|
509
|
+
reply={{
|
|
510
|
+
swipe: {
|
|
511
|
+
isEnabled: true,
|
|
512
|
+
direction: 'right',
|
|
513
|
+
onSwipe: setReplyMessage,
|
|
514
|
+
},
|
|
515
|
+
message: replyMessage,
|
|
516
|
+
onClear: () => setReplyMessage(null),
|
|
517
|
+
onPress: (msg) => scrollToMessage(msg._id),
|
|
518
|
+
}}
|
|
519
|
+
/>
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
#### Smooth Animations
|
|
523
|
+
|
|
524
|
+
The reply preview automatically animates when:
|
|
525
|
+
- **Appearing**: Smoothly expands from zero height with fade-in effect
|
|
526
|
+
- **Disappearing**: Smoothly collapses with fade-out effect
|
|
527
|
+
- **Content changes**: Smoothly transitions when replying to a different message
|
|
528
|
+
|
|
529
|
+
These animations use `react-native-reanimated` for 60fps performance.
|
|
530
|
+
|
|
397
531
|
### Scroll to Bottom
|
|
398
532
|
|
|
399
533
|
- **`isScrollToBottomEnabled`** _(Bool)_ - Enables the scroll to bottom Component (Default is false)
|
|
400
534
|
- **`scrollToBottomComponent`** _(Function)_ - Custom Scroll To Bottom Component container
|
|
401
535
|
- **`scrollToBottomOffset`** _(Integer)_ - Custom Height Offset upon which to begin showing Scroll To Bottom Component (Default is 200)
|
|
402
|
-
- **`scrollToBottomStyle`** _(Object)_ - Custom style for Bottom
|
|
536
|
+
- **`scrollToBottomStyle`** _(Object)_ - Custom style for Scroll To Bottom wrapper (position, bottom, right, etc.)
|
|
537
|
+
- **`scrollToBottomContentStyle`** _(Object)_ - Custom style for Scroll To Bottom content (size, background, shadow, etc.)
|
|
403
538
|
|
|
404
|
-
|
|
539
|
+
### Maintaining Scroll Position (AI Chatbots)
|
|
405
540
|
|
|
406
|
-
|
|
541
|
+
For AI chat interfaces where long responses arrive and you don't want to disrupt the user's reading position, use [`maintainVisibleContentPosition`](https://reactnative.dev/docs/scrollview#maintainvisiblecontentposition) via `listProps`:
|
|
407
542
|
|
|
408
|
-
|
|
543
|
+
```tsx
|
|
544
|
+
// Basic usage - always maintain scroll position
|
|
545
|
+
<GiftedChat
|
|
546
|
+
listProps={{
|
|
547
|
+
maintainVisibleContentPosition: {
|
|
548
|
+
minIndexForVisible: 0,
|
|
549
|
+
},
|
|
550
|
+
}}
|
|
551
|
+
/>
|
|
552
|
+
|
|
553
|
+
// With auto-scroll threshold - auto-scroll if within 10 pixels of newest content
|
|
554
|
+
<GiftedChat
|
|
555
|
+
listProps={{
|
|
556
|
+
maintainVisibleContentPosition: {
|
|
557
|
+
minIndexForVisible: 0,
|
|
558
|
+
autoscrollToTopThreshold: 10,
|
|
559
|
+
},
|
|
560
|
+
}}
|
|
561
|
+
/>
|
|
562
|
+
|
|
563
|
+
// Conditionally enable based on scroll state (recommended for chatbots)
|
|
564
|
+
const [isScrolledUp, setIsScrolledUp] = useState(false)
|
|
565
|
+
|
|
566
|
+
<GiftedChat
|
|
567
|
+
listProps={{
|
|
568
|
+
onScroll: (event) => {
|
|
569
|
+
setIsScrolledUp(event.contentOffset.y > 50)
|
|
570
|
+
},
|
|
571
|
+
maintainVisibleContentPosition: isScrolledUp
|
|
572
|
+
? { minIndexForVisible: 0, autoscrollToTopThreshold: 10 }
|
|
573
|
+
: undefined,
|
|
574
|
+
}}
|
|
575
|
+
/>
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
---
|
|
579
|
+
|
|
580
|
+
## đą Platform Notes
|
|
581
|
+
|
|
582
|
+
### Android
|
|
409
583
|
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
android:name=".MainActivity"
|
|
413
|
-
android:label="@string/app_name"
|
|
414
|
-
android:windowSoftInputMode="adjustResize"
|
|
415
|
-
android:configChanges="keyboard|keyboardHidden|orientation|screenSize">
|
|
416
|
-
```
|
|
584
|
+
<details>
|
|
585
|
+
<summary><strong>Keyboard configuration</strong></summary>
|
|
417
586
|
|
|
418
|
-
|
|
587
|
+
If you are using Create React Native App / Expo, no Android specific installation steps are required. Otherwise, we recommend modifying your project configuration:
|
|
419
588
|
|
|
420
|
-
|
|
589
|
+
Make sure you have `android:windowSoftInputMode="adjustResize"` in your `AndroidManifest.xml`:
|
|
421
590
|
|
|
591
|
+
```xml
|
|
592
|
+
<activity
|
|
593
|
+
android:name=".MainActivity"
|
|
594
|
+
android:label="@string/app_name"
|
|
595
|
+
android:windowSoftInputMode="adjustResize"
|
|
596
|
+
android:configChanges="keyboard|keyboardHidden|orientation|screenSize">
|
|
422
597
|
```
|
|
598
|
+
|
|
599
|
+
For **Expo**, you can append `KeyboardAvoidingView` after GiftedChat (Android only):
|
|
600
|
+
|
|
601
|
+
```jsx
|
|
423
602
|
<View style={{ flex: 1 }}>
|
|
424
603
|
<GiftedChat />
|
|
425
|
-
{
|
|
426
|
-
Platform.OS === 'android' && <KeyboardAvoidingView behavior="padding" />
|
|
427
|
-
}
|
|
604
|
+
{Platform.OS === 'android' && <KeyboardAvoidingView behavior="padding" />}
|
|
428
605
|
</View>
|
|
429
606
|
```
|
|
430
607
|
|
|
431
|
-
|
|
608
|
+
</details>
|
|
432
609
|
|
|
433
|
-
|
|
610
|
+
### Web (react-native-web)
|
|
434
611
|
|
|
435
|
-
|
|
436
|
-
|
|
612
|
+
<details>
|
|
613
|
+
<summary><strong>With create-react-app</strong></summary>
|
|
614
|
+
|
|
615
|
+
1. Install react-app-rewired: `yarn add -D react-app-rewired`
|
|
616
|
+
2. Create `config-overrides.js`:
|
|
437
617
|
|
|
438
618
|
```js
|
|
439
619
|
module.exports = function override(config, env) {
|
|
@@ -453,23 +633,30 @@ module.exports = function override(config, env) {
|
|
|
453
633
|
},
|
|
454
634
|
},
|
|
455
635
|
})
|
|
456
|
-
|
|
457
636
|
return config
|
|
458
637
|
}
|
|
459
638
|
```
|
|
460
639
|
|
|
461
|
-
>
|
|
640
|
+
> **Examples:**
|
|
641
|
+
> - [xcarpentier/gifted-chat-web-demo](https://github.com/xcarpentier/gifted-chat-web-demo)
|
|
642
|
+
> - [Gatsby example](https://github.com/xcarpentier/clean-archi-boilerplate/tree/develop/apps/web)
|
|
462
643
|
|
|
463
|
-
>
|
|
644
|
+
</details>
|
|
464
645
|
|
|
465
|
-
|
|
466
|
-
|
|
646
|
+
---
|
|
647
|
+
|
|
648
|
+
## đ§Ē Testing
|
|
649
|
+
|
|
650
|
+
<details>
|
|
651
|
+
<summary><strong>Triggering layout events in tests</strong></summary>
|
|
467
652
|
|
|
468
|
-
|
|
653
|
+
`TEST_ID` is exported as constants that can be used in your testing library of choice.
|
|
654
|
+
|
|
655
|
+
Gifted Chat uses `onLayout` to determine the height of the chat container. To trigger `onLayout` during your tests:
|
|
469
656
|
|
|
470
657
|
```typescript
|
|
471
|
-
const WIDTH = 200
|
|
472
|
-
const HEIGHT = 2000
|
|
658
|
+
const WIDTH = 200
|
|
659
|
+
const HEIGHT = 2000
|
|
473
660
|
|
|
474
661
|
const loadingWrapper = getByTestId(TEST_ID.LOADING_WRAPPER)
|
|
475
662
|
fireEvent(loadingWrapper, 'layout', {
|
|
@@ -482,37 +669,144 @@ fireEvent(loadingWrapper, 'layout', {
|
|
|
482
669
|
})
|
|
483
670
|
```
|
|
484
671
|
|
|
485
|
-
|
|
672
|
+
</details>
|
|
673
|
+
|
|
674
|
+
---
|
|
675
|
+
|
|
676
|
+
## đĻ Example App
|
|
677
|
+
|
|
678
|
+
The repository includes a comprehensive example app demonstrating all features:
|
|
679
|
+
|
|
680
|
+
```bash
|
|
681
|
+
# Clone and install
|
|
682
|
+
git clone https://github.com/FaridSafi/react-native-gifted-chat.git
|
|
683
|
+
cd react-native-gifted-chat/example
|
|
684
|
+
yarn install
|
|
486
685
|
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
- [How can I change the color of the message box?](https://github.com/FaridSafi/react-native-gifted-chat/issues/640)
|
|
490
|
-
- [Is there a way to manually dismiss the keyboard?](https://github.com/FaridSafi/react-native-gifted-chat/issues/647)
|
|
491
|
-
- [I want to implement a popover that pops right after clicking on a specific avatar,
|
|
492
|
-
what is the best implementation in this case and how?](https://github.com/FaridSafi/react-native-gifted-chat/issues/660)
|
|
493
|
-
- [Why TextInput is hidden on Android?](https://github.com/FaridSafi/react-native-gifted-chat/issues/680#issuecomment-359699364)
|
|
494
|
-
- [How to use renderLoading?](https://github.com/FaridSafi/react-native-gifted-chat/issues/298)
|
|
495
|
-
- [Can I use MySql to save the message?](https://github.com/FaridSafi/react-native-gifted-chat/issues/738)
|
|
686
|
+
# Run on iOS
|
|
687
|
+
npx expo run:ios
|
|
496
688
|
|
|
497
|
-
|
|
689
|
+
# Run on Android
|
|
690
|
+
npx expo run:android
|
|
691
|
+
|
|
692
|
+
# Run on Web
|
|
693
|
+
npx expo start --web
|
|
694
|
+
```
|
|
695
|
+
|
|
696
|
+
The example app showcases:
|
|
697
|
+
- đŦ Basic chat functionality
|
|
698
|
+
- đ¨ Custom message bubbles and avatars
|
|
699
|
+
- âŠī¸ Reply to messages with swipe gesture
|
|
700
|
+
- ⥠Quick replies (bot-style)
|
|
701
|
+
- âī¸ Typing indicators
|
|
702
|
+
- đ Attachment actions
|
|
703
|
+
- đ Link parsing and custom matchers
|
|
704
|
+
- đ Web compatibility
|
|
705
|
+
|
|
706
|
+
---
|
|
498
707
|
|
|
499
|
-
|
|
500
|
-
1. Please ask on StackOverflow first: https://stackoverflow.com/questions/tagged/react-native-gifted-chat
|
|
501
|
-
1. Find responses in existing issues
|
|
502
|
-
1. Try to keep issues for issues
|
|
708
|
+
## â Troubleshooting
|
|
503
709
|
|
|
504
|
-
|
|
710
|
+
<details>
|
|
711
|
+
<summary><strong>TextInput is hidden on Android</strong></summary>
|
|
505
712
|
|
|
506
|
-
|
|
713
|
+
Make sure you have `android:windowSoftInputMode="adjustResize"` in your `AndroidManifest.xml`. See [Android configuration](#android) above.
|
|
507
714
|
|
|
508
|
-
|
|
715
|
+
</details>
|
|
509
716
|
|
|
510
|
-
|
|
717
|
+
<details>
|
|
718
|
+
<summary><strong>How to set Bubble color for each user?</strong></summary>
|
|
511
719
|
|
|
512
|
-
|
|
720
|
+
See [this issue](https://github.com/FaridSafi/react-native-gifted-chat/issues/672) for examples.
|
|
513
721
|
|
|
514
|
-
|
|
722
|
+
</details>
|
|
515
723
|
|
|
516
|
-
|
|
724
|
+
<details>
|
|
725
|
+
<summary><strong>How to customize InputToolbar styles?</strong></summary>
|
|
517
726
|
|
|
518
|
-
|
|
727
|
+
See [this issue](https://github.com/FaridSafi/react-native-gifted-chat/issues/662) for examples.
|
|
728
|
+
|
|
729
|
+
</details>
|
|
730
|
+
|
|
731
|
+
<details>
|
|
732
|
+
<summary><strong>How to manually dismiss the keyboard?</strong></summary>
|
|
733
|
+
|
|
734
|
+
See [this issue](https://github.com/FaridSafi/react-native-gifted-chat/issues/647) for examples.
|
|
735
|
+
|
|
736
|
+
</details>
|
|
737
|
+
|
|
738
|
+
<details>
|
|
739
|
+
<summary><strong>How to use renderLoading?</strong></summary>
|
|
740
|
+
|
|
741
|
+
See [this issue](https://github.com/FaridSafi/react-native-gifted-chat/issues/298) for examples.
|
|
742
|
+
|
|
743
|
+
</details>
|
|
744
|
+
|
|
745
|
+
---
|
|
746
|
+
|
|
747
|
+
## đ¤ Have a Question?
|
|
748
|
+
|
|
749
|
+
1. Check this README first
|
|
750
|
+
2. Search [existing issues](https://github.com/FaridSafi/react-native-gifted-chat/issues)
|
|
751
|
+
3. Ask on [StackOverflow](https://stackoverflow.com/questions/tagged/react-native-gifted-chat)
|
|
752
|
+
4. Open a new issue if needed
|
|
753
|
+
|
|
754
|
+
---
|
|
755
|
+
|
|
756
|
+
## đ¤ Contributing
|
|
757
|
+
|
|
758
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
759
|
+
|
|
760
|
+
1. Fork the repository
|
|
761
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
762
|
+
3. Install dependencies (`yarn install`)
|
|
763
|
+
4. Make your changes
|
|
764
|
+
5. Run tests (`yarn test`)
|
|
765
|
+
6. Run linting (`yarn lint`)
|
|
766
|
+
7. Build the library (`yarn build`)
|
|
767
|
+
8. Commit your changes (`git commit -m 'Add amazing feature'`)
|
|
768
|
+
9. Push to the branch (`git push origin feature/amazing-feature`)
|
|
769
|
+
10. Open a Pull Request
|
|
770
|
+
|
|
771
|
+
### Development Setup
|
|
772
|
+
|
|
773
|
+
```bash
|
|
774
|
+
# Install dependencies
|
|
775
|
+
yarn install
|
|
776
|
+
|
|
777
|
+
# Build the library
|
|
778
|
+
yarn build
|
|
779
|
+
|
|
780
|
+
# Run tests
|
|
781
|
+
yarn test
|
|
782
|
+
|
|
783
|
+
# Run linting
|
|
784
|
+
yarn lint
|
|
785
|
+
|
|
786
|
+
# Full validation
|
|
787
|
+
yarn prepublishOnly
|
|
788
|
+
```
|
|
789
|
+
|
|
790
|
+
---
|
|
791
|
+
|
|
792
|
+
## đĨ Authors
|
|
793
|
+
|
|
794
|
+
**Original Author:** [Farid Safi](https://www.x.com/FaridSafi)
|
|
795
|
+
|
|
796
|
+
**Co-maintainer:** [Xavier Carpentier](https://www.x.com/xcapetir) - [Hire Xavier](https://xaviercarpentier.com)
|
|
797
|
+
|
|
798
|
+
**Maintainer:** [Kesha Antonov](https://github.com/kesha-antonov)
|
|
799
|
+
|
|
800
|
+
> Please note that this project is maintained in free time. If you find it helpful, please consider [becoming a sponsor](https://github.com/sponsors/kesha-antonov).
|
|
801
|
+
|
|
802
|
+
---
|
|
803
|
+
|
|
804
|
+
## đ License
|
|
805
|
+
|
|
806
|
+
[MIT](LICENSE)
|
|
807
|
+
|
|
808
|
+
---
|
|
809
|
+
|
|
810
|
+
<p align="center">
|
|
811
|
+
<sub>Built with â¤ī¸ by the React Native community</sub>
|
|
812
|
+
</p>
|