react-native-gifted-chat 2.8.2-alpha.1 → 2.8.2-alpha.2

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 (40) hide show
  1. package/README.md +43 -19
  2. package/package.json +10 -11
  3. package/src/Actions.tsx +1 -1
  4. package/src/Avatar.tsx +1 -1
  5. package/src/Bubble/index.tsx +13 -10
  6. package/src/Bubble/types.ts +5 -4
  7. package/src/Composer.tsx +1 -1
  8. package/src/Day/index.tsx +3 -3
  9. package/src/GiftedAvatar.tsx +2 -2
  10. package/src/GiftedChat/index.tsx +48 -44
  11. package/src/GiftedChat/styles.ts +3 -0
  12. package/src/GiftedChat/types.ts +13 -16
  13. package/src/InputToolbar.tsx +2 -2
  14. package/src/LoadEarlier.tsx +3 -3
  15. package/src/Message/index.tsx +4 -18
  16. package/src/Message/types.ts +2 -2
  17. package/src/MessageAudio.tsx +1 -1
  18. package/src/MessageContainer/components/DayAnimated/index.tsx +2 -2
  19. package/src/MessageContainer/components/Item/index.tsx +3 -3
  20. package/src/MessageContainer/components/Item/types.ts +1 -1
  21. package/src/MessageContainer/index.tsx +10 -10
  22. package/src/MessageContainer/types.ts +2 -2
  23. package/src/MessageImage.tsx +119 -17
  24. package/src/MessageText.tsx +10 -45
  25. package/src/MessageVideo.tsx +1 -1
  26. package/src/QuickReplies.tsx +2 -2
  27. package/src/Send.tsx +3 -4
  28. package/src/SystemMessage.tsx +1 -1
  29. package/src/Time.tsx +1 -1
  30. package/src/TypingIndicator/index.tsx +2 -2
  31. package/src/__tests__/DayAnimated.test.tsx +2 -2
  32. package/src/__tests__/GiftedChat.test.tsx +3 -3
  33. package/src/__tests__/__snapshots__/Actions.test.tsx.snap +39 -7
  34. package/src/__tests__/__snapshots__/GiftedChat.test.tsx.snap +20 -22
  35. package/src/__tests__/__snapshots__/LoadEarlier.test.tsx.snap +37 -6
  36. package/src/__tests__/__snapshots__/MessageImage.test.tsx.snap +34 -15
  37. package/src/__tests__/__snapshots__/Send.test.tsx.snap +70 -10
  38. package/src/components/TouchableOpacity.tsx +45 -0
  39. package/src/types.ts +0 -2
  40. package/src/utils.ts +2 -2
package/README.md CHANGED
@@ -85,21 +85,19 @@
85
85
 
86
86
  ## Features
87
87
 
88
- - 🎉 **_`react-native-web`able_ (since 0.10.0)** [web configuration](#react-native-web)
89
- - Write with **TypeScript** (since 0.8.0)
90
88
  - Fully customizable components
91
89
  - Composer actions (to attach photos, etc.)
92
90
  - Load earlier messages
93
91
  - Copy messages to clipboard
94
- - Touchable links using [react-native-parsed-text](https://github.com/taskrabbit/react-native-parsed-text)
92
+ - Touchable links using [react-native-autolink](https://github.com/joshswan/react-native-autolink)
95
93
  - Avatar as user's initials
96
94
  - Localized dates
97
95
  - Multi-line TextInput
98
96
  - InputToolbar avoiding keyboard
99
- - Redux support
100
97
  - System message
101
98
  - Quick Reply messages (bot)
102
99
  - Typing indicator
100
+ - react-native-web [web configuration](#react-native-web)
103
101
 
104
102
  # Getting started
105
103
 
@@ -117,18 +115,18 @@ Readme for this version: [2.6.5 readme](https://github.com/FaridSafi/react-nativ
117
115
 
118
116
  Yarn:
119
117
  ```bash
120
- yarn add react-native-gifted-chat react-native-reanimated react-native-keyboard-controller
118
+ yarn add react-native-gifted-chat react-native-reanimated react-native-keyboard-controller react-native-gesture-handler react-native-safe-area-context
121
119
  ```
122
120
 
123
121
  Npm:
124
122
 
125
123
  ```bash
126
- npm install --save react-native-gifted-chat react-native-reanimated react-native-keyboard-controller
124
+ npm install --save react-native-gifted-chat react-native-reanimated react-native-keyboard-controller react-native-gesture-handler react-native-safe-area-context
127
125
  ```
128
126
 
129
127
  Expo
130
128
  ```bash
131
- npx expo install react-native-gifted-chat react-native-reanimated react-native-keyboard-controller
129
+ npx expo install react-native-gifted-chat react-native-reanimated react-native-keyboard-controller react-native-gesture-handler react-native-safe-area-context
132
130
  ```
133
131
 
134
132
  ### Non-expo users
@@ -173,9 +171,15 @@ fireEvent(loadingWrapper, 'layout', {
173
171
  ```jsx
174
172
  import React, { useState, useCallback, useEffect } from 'react'
175
173
  import { GiftedChat } from 'react-native-gifted-chat'
174
+ import { useSafeAreaInsets } from 'react-native-safe-area-context'
176
175
 
177
176
  export function Example() {
178
177
  const [messages, setMessages] = useState([])
178
+ const insets = useSafeAreaInsets()
179
+
180
+ // If you have a tab bar, include its height
181
+ const tabbarHeight = 50
182
+ const keyboardBottomOffset = insets.bottom + tabbarHeight
179
183
 
180
184
  useEffect(() => {
181
185
  setMessages([
@@ -205,6 +209,7 @@ export function Example() {
205
209
  user={{
206
210
  _id: 1,
207
211
  }}
212
+ keyboardBottomOffset={keyboardBottomOffset}
208
213
  />
209
214
  )
210
215
  }
@@ -212,7 +217,7 @@ export function Example() {
212
217
 
213
218
  ## Advanced example
214
219
 
215
- See [`App.tsx`](https://github.com/FaridSafi/react-native-gifted-chat/blob/master/example/App.tsx) for a working demo!
220
+ See [`examples`](example) for a working demo!
216
221
 
217
222
  ## "Slack" example
218
223
 
@@ -354,8 +359,8 @@ interface QuickReplies {
354
359
  - **`textInputRef`** _(TextInput ref)_ - Ref to the text input
355
360
  - **`messages`** _(Array)_ - Messages to display
356
361
  - **`isTyping`** _(Bool)_ - Typing Indicator state; default `false`. If you use`renderFooter` it will override this.
362
+ - **`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.
357
363
  - **`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`
358
- - **`disableKeyboardController`** _(Bool)_ - Completely disable react-native-keyboard-controller. Useful when using react-native-navigation or other conflicting keyboard libraries; default is `false`
359
364
  - **`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))
360
365
  - **`onInputTextChanged`** _(Function)_ - Callback when the input text changes
361
366
  - **`messageIdGenerator`** _(Function)_ - Generate an id for new messages. Defaults to UUID v4, generated by [uuid](https://github.com/kelektiv/node-uuid)
@@ -391,7 +396,6 @@ interface QuickReplies {
391
396
  - **`renderMessageVideo`** _(Function)_ - Custom message video
392
397
  - **`imageProps`** _(Object)_ - Extra props to be passed to the [`<Image>`](https://reactnative.dev/docs/image.html) component created by the default `renderMessageImage`
393
398
  - **`videoProps`** _(Object)_ - Extra props to be passed to the video component created by the required `renderMessageVideo`
394
- - **`lightboxProps`** _(Object)_ - Extra props to be passed to the `MessageImage`'s [Lightbox](https://github.com/oblador/react-native-lightbox)
395
399
  - **`isCustomViewBottom`** _(Bool)_ - Determine whether renderCustomView is displayed before or after the text, image and video views; default is `false`
396
400
  - **`renderCustomView`** _(Function)_ - Custom view inside the bubble
397
401
  - **`renderDay`** _(Function)_ - Custom day above a message
@@ -405,22 +409,42 @@ interface QuickReplies {
405
409
  - **`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))
406
410
  - **`renderAccessory`** _(Function)_ - Custom second line of actions below the message composer
407
411
  - **`onPressActionButton`** _(Function)_ - Callback when the Action button is pressed (if set, the default `actionSheet` will not be used)
408
- - **`bottomOffset`** _(Integer)_ - Distance of the chat from the bottom of the screen (e.g. useful if you display a tab bar)
409
412
  - **`focusOnInputWhenOpeningKeyboard`** _(Bool)_ - Focus on <TextInput> automatically when opening the keyboard; default `true`
410
413
  - **`minInputToolbarHeight`** _(Integer)_ - Minimum height of the input toolbar; default is `44`
411
414
  - **`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
412
415
  - **`textInputProps`** _(Object)_ - props to be passed to the [`<TextInput>`](https://reactnative.dev/docs/textinput.html).
413
- - **`matchers`** _(Array)_ - Custom matchers for [react-native-autolink](https://github.com/joshswan/react-native-autolink) used to linking message content (like URLs and phone numbers), e.g.:
416
+ - **`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:
417
+ - `matchers` - Custom matchers for linking message content (like URLs, phone numbers, hashtags, mentions)
418
+ - `linkStyle` - Custom style for links
419
+ - `email` - Enable/disable email parsing (default: true)
420
+ - `phone` - Enable/disable phone number parsing (default: true)
421
+ - `url` - Enable/disable URL parsing (default: true)
422
+
423
+ Example:
414
424
 
415
425
  ```js
416
- <GiftedChat
417
- matchers={[
418
- { type: 'phone', style: linkStyle, onPress: onPressPhoneNumber },
419
- { pattern: /#(\w+)/, style: [linkStyle, styles.hashtag], onPress: onPressHashtag },
420
- ]}
421
- />
426
+ <GiftedChat
427
+ messageTextProps={{
428
+ matchers: [
429
+ {
430
+ pattern: /#(\w+)/g,
431
+ style: { color: '#0084ff', fontWeight: 'bold' },
432
+ onPress: (match) => console.log('Hashtag:', match.getAnchorText()),
433
+ },
434
+ {
435
+ pattern: /(?<![\.\w])@(?!__ELEMENT-)([\w-]+)/g,
436
+ style: { color: '#0084ff', fontWeight: 'bold' },
437
+ onPress: (match) => console.log('Mention:', match.getAnchorText()),
438
+ },
439
+ ],
440
+ linkStyle: { left: { color: 'blue' }, right: { color: 'lightblue' } },
441
+ phone: false,
442
+ }}
443
+ />
422
444
  ```
423
445
 
446
+ - **`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).
447
+
424
448
  - **`extraData`** _(Object)_ - Extra props for re-rendering FlatList on demand. This will be useful for rendering footer etc.
425
449
  - **`minComposerHeight`** _(Object)_ - Custom min-height of the composer.
426
450
  - **`maxComposerHeight`** _(Object)_ - Custom max height of the composer.
@@ -514,7 +538,7 @@ If you use React Navigation, additional handling may be required to account for
514
538
  module.exports = function override(config, env) {
515
539
  config.module.rules.push({
516
540
  test: /\.js$/,
517
- exclude: /node_modules[/\\](?!react-native-gifted-chat|react-native-lightbox|react-native-parsed-text)/,
541
+ exclude: /node_modules[/\\](?!react-native-gifted-chat)/,
518
542
  use: {
519
543
  loader: 'babel-loader',
520
544
  options: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-gifted-chat",
3
- "version": "2.8.2-alpha.1",
3
+ "version": "2.8.2-alpha.2",
4
4
  "description": "The most complete chat UI for React Native",
5
5
  "keywords": [
6
6
  "android",
@@ -53,8 +53,7 @@
53
53
  "dayjs": "^1.11.19",
54
54
  "lodash.isequal": "^4.5.0",
55
55
  "react-native-autolink": "^4.2.0",
56
- "react-native-communications": "^2.2.1",
57
- "react-native-lightbox-v2": "^0.9.2"
56
+ "react-native-zoom-reanimated": "^1.4.10"
58
57
  },
59
58
  "devDependencies": {
60
59
  "@babel/core": "^7.28.5",
@@ -80,16 +79,12 @@
80
79
  "@typescript-eslint/eslint-plugin": "^8.46.4",
81
80
  "@typescript-eslint/parser": "^8.46.4",
82
81
  "babel-jest": "^29.7.0",
83
- "eslint": "^8.57.0",
84
- "eslint-config-standard": "^17.1.0",
85
- "eslint-config-standard-jsx": "^11.0.0",
82
+ "eslint": "^9.18.0",
86
83
  "eslint-plugin-import": "^2.32.0",
87
84
  "eslint-plugin-jest": "^28.11.0",
88
- "eslint-plugin-json": "^4.0.1",
89
- "eslint-plugin-n": "^17.23.1",
90
- "eslint-plugin-node": "^11.1.0",
91
- "eslint-plugin-promise": "^7.2.1",
85
+ "eslint-plugin-perfectionist": "^4.15.1",
92
86
  "eslint-plugin-react": "^7.37.5",
87
+ "eslint-plugin-react-hooks": "^5.1.0",
93
88
  "husky": "^9.1.7",
94
89
  "jest": "^29.7.0",
95
90
  "json": "^11.0.0",
@@ -97,16 +92,20 @@
97
92
  "react": "19.1.0",
98
93
  "react-dom": "19.1.0",
99
94
  "react-native": "0.81.5",
95
+ "react-native-gesture-handler": "^2.29.1",
100
96
  "react-native-keyboard-controller": "^1.19.5",
101
97
  "react-native-reanimated": "^3.19.4",
98
+ "react-native-safe-area-context": "^5.6.2",
102
99
  "react-test-renderer": "19.1.0",
103
100
  "typescript": "^5.9.3"
104
101
  },
105
102
  "peerDependencies": {
106
103
  "react": ">=18.0.0",
107
104
  "react-native": "*",
105
+ "react-native-gesture-handler": ">=2.0.0",
108
106
  "react-native-keyboard-controller": ">=1.0.0",
109
- "react-native-reanimated": ">=3.0.0 || ^4.0.0"
107
+ "react-native-reanimated": ">=3.0.0 || ^4.0.0",
108
+ "react-native-safe-area-context": ">=5.0.0"
110
109
  },
111
110
  "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e",
112
111
  "engines": {
package/src/Actions.tsx CHANGED
@@ -2,13 +2,13 @@ import React, { ReactNode, useCallback } from 'react'
2
2
  import {
3
3
  StyleSheet,
4
4
  Text,
5
- TouchableOpacity,
6
5
  View,
7
6
  StyleProp,
8
7
  ViewStyle,
9
8
  TextStyle,
10
9
  } from 'react-native'
11
10
  import Color from './Color'
11
+ import { TouchableOpacity } from './components/TouchableOpacity'
12
12
  import { useChatContext } from './GiftedChatContext'
13
13
 
14
14
  import stylesCommon from './styles'
package/src/Avatar.tsx CHANGED
@@ -7,8 +7,8 @@ import {
7
7
  ViewStyle,
8
8
  } from 'react-native'
9
9
  import { GiftedAvatar } from './GiftedAvatar'
10
- import { isSameUser, isSameDay } from './utils'
11
10
  import { IMessage, LeftRightStyle, User } from './types'
11
+ import { isSameUser, isSameDay } from './utils'
12
12
 
13
13
  interface Styles {
14
14
  left: {
@@ -6,19 +6,19 @@ import {
6
6
  } from 'react-native'
7
7
 
8
8
  import { useChatContext } from '../GiftedChatContext'
9
- import { QuickReplies } from '../QuickReplies'
10
- import { MessageText } from '../MessageText'
9
+ import { MessageAudio } from '../MessageAudio'
11
10
  import { MessageImage } from '../MessageImage'
11
+ import { MessageText } from '../MessageText'
12
12
  import { MessageVideo } from '../MessageVideo'
13
- import { MessageAudio } from '../MessageAudio'
14
- import { Time } from '../Time'
13
+ import { QuickReplies } from '../QuickReplies'
14
+ import stylesCommon from '../styles'
15
15
 
16
- import { isSameUser, isSameDay } from '../utils'
16
+ import { Time } from '../Time'
17
17
  import { IMessage } from '../types'
18
- import { BubbleProps } from './types'
18
+ import { isSameUser, isSameDay } from '../utils'
19
19
 
20
- import stylesCommon from '../styles'
21
20
  import styles from './styles'
21
+ import { BubbleProps, RenderMessageTextProps } from './types'
22
22
 
23
23
  export * from './types'
24
24
 
@@ -142,14 +142,17 @@ const Bubble = <TMessage extends IMessage = IMessage>(props: BubbleProps<TMessag
142
142
  /* eslint-disable @typescript-eslint/no-unused-vars */
143
143
  containerStyle,
144
144
  wrapperStyle,
145
+ messageTextProps,
145
146
  /* eslint-enable @typescript-eslint/no-unused-vars */
146
- ...messageTextProps
147
+ ...messageTextPropsRest
147
148
  } = props
148
149
 
150
+ const combinedProps = { ...messageTextPropsRest, ...messageTextProps } as RenderMessageTextProps<TMessage>
151
+
149
152
  if (props.renderMessageText)
150
- return props.renderMessageText(messageTextProps)
153
+ return props.renderMessageText(combinedProps)
151
154
 
152
- return <MessageText {...messageTextProps} />
155
+ return <MessageText {...combinedProps} />
153
156
  }
154
157
 
155
158
  return null
@@ -4,9 +4,9 @@ import {
4
4
  ViewStyle,
5
5
  TextStyle,
6
6
  } from 'react-native'
7
- import { QuickRepliesProps } from '../QuickReplies'
8
- import { MessageTextProps, MessageOption } from '../MessageText'
9
7
  import { MessageImageProps } from '../MessageImage'
8
+ import { MessageTextProps, MessageOption } from '../MessageText'
9
+ import { QuickRepliesProps } from '../QuickReplies'
10
10
  import { TimeProps } from '../Time'
11
11
  import {
12
12
  User,
@@ -18,7 +18,7 @@ import {
18
18
  MessageAudioProps,
19
19
  } from '../types'
20
20
 
21
- /* eslint-disable no-use-before-define */
21
+
22
22
  export type RenderMessageImageProps<TMessage extends IMessage> = Omit<
23
23
  BubbleProps<TMessage>,
24
24
  'containerStyle' | 'wrapperStyle'
@@ -42,7 +42,7 @@ export type RenderMessageTextProps<TMessage extends IMessage> = Omit<
42
42
  'containerStyle' | 'wrapperStyle' | 'options'
43
43
  > &
44
44
  MessageTextProps<TMessage>
45
- /* eslint-enable no-use-before-define */
45
+
46
46
 
47
47
  export interface BubbleProps<TMessage extends IMessage> {
48
48
  user?: User
@@ -66,6 +66,7 @@ export interface BubbleProps<TMessage extends IMessage> {
66
66
  quickReplyStyle?: StyleProp<ViewStyle>
67
67
  quickReplyTextStyle?: StyleProp<TextStyle>
68
68
  quickReplyContainerStyle?: StyleProp<ViewStyle>
69
+ messageTextProps?: Partial<MessageTextProps<TMessage>>
69
70
  onPressMessage?(context?: unknown, message?: unknown): void
70
71
  onLongPressMessage?(context?: unknown, message?: unknown): void
71
72
  onQuickReply?(replies: Reply[]): void
package/src/Composer.tsx CHANGED
@@ -8,8 +8,8 @@ import {
8
8
  TextInputContentSizeChangeEventData,
9
9
  useColorScheme,
10
10
  } from 'react-native'
11
- import { MIN_COMPOSER_HEIGHT } from './Constant'
12
11
  import Color from './Color'
12
+ import { MIN_COMPOSER_HEIGHT } from './Constant'
13
13
  import stylesCommon from './styles'
14
14
 
15
15
  export interface ComposerProps {
package/src/Day/index.tsx CHANGED
@@ -4,15 +4,15 @@ import {
4
4
  View,
5
5
  } from 'react-native'
6
6
  import dayjs from 'dayjs'
7
- import relativeTime from 'dayjs/plugin/relativeTime'
8
7
  import calendar from 'dayjs/plugin/calendar'
8
+ import relativeTime from 'dayjs/plugin/relativeTime'
9
9
 
10
10
  import { DATE_FORMAT } from '../Constant'
11
- import { DayProps } from './types'
12
-
13
11
  import { useChatContext } from '../GiftedChatContext'
12
+
14
13
  import stylesCommon from '../styles'
15
14
  import styles from './styles'
15
+ import { DayProps } from './types'
16
16
 
17
17
  export * from './types'
18
18
 
@@ -2,7 +2,6 @@ import React, { useCallback, useMemo } from 'react'
2
2
  import {
3
3
  Image,
4
4
  Text,
5
- TouchableOpacity,
6
5
  View,
7
6
  StyleSheet,
8
7
  StyleProp,
@@ -10,8 +9,9 @@ import {
10
9
  TextStyle,
11
10
  } from 'react-native'
12
11
  import Color from './Color'
13
- import { User } from './types'
12
+ import { TouchableOpacity } from './components/TouchableOpacity'
14
13
  import stylesCommon from './styles'
14
+ import { User } from './types'
15
15
 
16
16
  const {
17
17
  carrot,
@@ -7,17 +7,26 @@ import React, {
7
7
  useCallback,
8
8
  RefObject,
9
9
  } from 'react'
10
+ import {
11
+ TextInput,
12
+ View,
13
+ LayoutChangeEvent,
14
+ } from 'react-native'
10
15
  import {
11
16
  ActionSheetProvider,
12
17
  ActionSheetProviderRef,
13
18
  } from '@expo/react-native-action-sheet'
14
19
  import dayjs from 'dayjs'
15
20
  import localizedFormat from 'dayjs/plugin/localizedFormat'
16
- import {
17
- TextInput,
18
- View,
19
- LayoutChangeEvent,
20
- } from 'react-native'
21
+ import { GestureHandlerRootView } from 'react-native-gesture-handler'
22
+ import { KeyboardProvider, useReanimatedKeyboardAnimation } from 'react-native-keyboard-controller'
23
+ import Animated, {
24
+ useAnimatedStyle,
25
+ useAnimatedReaction,
26
+ useSharedValue,
27
+ withTiming,
28
+ runOnJS,
29
+ } from 'react-native-reanimated'
21
30
  import { Actions } from '../Actions'
22
31
  import { Avatar } from '../Avatar'
23
32
  import Bubble from '../Bubble'
@@ -32,25 +41,17 @@ import Message from '../Message'
32
41
  import MessageContainer, { AnimatedList } from '../MessageContainer'
33
42
  import { MessageImage } from '../MessageImage'
34
43
  import { MessageText } from '../MessageText'
35
- import {
36
- IMessage,
37
- } from '../types'
38
44
  import { Send } from '../Send'
45
+ import stylesCommon from '../styles'
39
46
  import { SystemMessage } from '../SystemMessage'
40
47
  import { Time } from '../Time'
41
- import * as utils from '../utils'
42
- import Animated, {
43
- useAnimatedStyle,
44
- useAnimatedReaction,
45
- useSharedValue,
46
- withTiming,
47
- runOnJS,
48
- } from 'react-native-reanimated'
49
- import { KeyboardProvider, useReanimatedKeyboardAnimation } from 'react-native-keyboard-controller'
50
- import { GiftedChatProps } from './types'
48
+ import {
49
+ IMessage,
50
+ } from '../types'
51
51
 
52
- import stylesCommon from '../styles'
52
+ import * as utils from '../utils'
53
53
  import styles from './styles'
54
+ import { GiftedChatProps } from './types'
54
55
 
55
56
  dayjs.extend(localizedFormat)
56
57
 
@@ -75,14 +76,13 @@ function GiftedChat<TMessage extends IMessage = IMessage> (
75
76
  textInputProps,
76
77
  renderChatFooter,
77
78
  renderInputToolbar,
78
- bottomOffset = 0,
79
+ keyboardBottomOffset = 0,
79
80
  focusOnInputWhenOpeningKeyboard = true,
80
81
  onInputTextChanged,
81
82
  inverted = true,
82
83
  minComposerHeight = MIN_COMPOSER_HEIGHT,
83
84
  maxComposerHeight = MAX_COMPOSER_HEIGHT,
84
85
  isKeyboardInternallyHandled = true,
85
- disableKeyboardController = false,
86
86
  } = props
87
87
 
88
88
  const actionSheetRef = useRef<ActionSheetProviderRef>(null)
@@ -108,23 +108,24 @@ function GiftedChat<TMessage extends IMessage = IMessage> (
108
108
  // Always call the hook, but conditionally use its data
109
109
  const keyboardControllerData = useReanimatedKeyboardAnimation()
110
110
 
111
- // Create a mock keyboard object when disabled
111
+ // Create a mock keyboard object when keyboard is not internally handled
112
112
  const keyboard = useMemo(() => {
113
- if (disableKeyboardController)
113
+ if (!isKeyboardInternallyHandled)
114
114
  return { height: { value: 0 } }
115
+
115
116
  return keyboardControllerData
116
- }, [disableKeyboardController, keyboardControllerData])
117
+ }, [isKeyboardInternallyHandled, keyboardControllerData])
117
118
 
118
119
  const trackingKeyboardMovement = useSharedValue(false)
119
- const keyboardOffsetBottom = useSharedValue(0)
120
+ const keyboardBottomOffsetAnim = useSharedValue(0)
120
121
 
121
122
  const contentStyleAnim = useAnimatedStyle(
122
123
  () => ({
123
124
  transform: [
124
- { translateY: keyboard.height.value - keyboardOffsetBottom.value },
125
+ { translateY: keyboard.height.value + keyboardBottomOffsetAnim.value },
125
126
  ],
126
127
  }),
127
- [keyboard, keyboardOffsetBottom]
128
+ [keyboard, keyboardBottomOffsetAnim]
128
129
  )
129
130
 
130
131
  const getTextFromProp = useCallback(
@@ -278,6 +279,7 @@ function GiftedChat<TMessage extends IMessage = IMessage> (
278
279
 
279
280
  const onInitialLayoutViewLayout = useCallback(
280
281
  (e: LayoutChangeEvent) => {
282
+ console.log('onInitialLayoutViewLayout', e.nativeEvent.layout.height)
281
283
  if (isInitialized)
282
284
  return
283
285
 
@@ -349,23 +351,23 @@ function GiftedChat<TMessage extends IMessage = IMessage> (
349
351
  setText(props.text)
350
352
  }, [props.text])
351
353
 
352
- // Only set up keyboard animation when keyboard controller is enabled
354
+ // Only set up keyboard animation when keyboard is internally handled
353
355
  useAnimatedReaction(
354
- () => disableKeyboardController ? 0 : -keyboard.height.value,
356
+ () => isKeyboardInternallyHandled ? keyboard.height.value : 0,
355
357
  (value, prevValue) => {
356
- // Skip keyboard handling when disabled
357
- if (disableKeyboardController)
358
+ // Skip keyboard handling when not internally handled
359
+ if (!isKeyboardInternallyHandled)
358
360
  return
359
361
 
360
362
  if (prevValue !== null && value !== prevValue) {
361
- const isKeyboardMovingUp = value > prevValue
363
+ const isKeyboardMovingUp = value < prevValue
362
364
  if (isKeyboardMovingUp !== trackingKeyboardMovement.value) {
363
365
  trackingKeyboardMovement.value = isKeyboardMovingUp
364
- keyboardOffsetBottom.value = withTiming(
365
- isKeyboardMovingUp ? bottomOffset : 0,
366
+ keyboardBottomOffsetAnim.value = withTiming(
367
+ isKeyboardMovingUp ? keyboardBottomOffset : 0,
366
368
  {
367
- // If `bottomOffset` exists, we change the duration to a smaller value to fix the delay in the keyboard animation speed
368
- duration: bottomOffset ? 150 : 400,
369
+ // If `keyboardBottomOffset` exists, we change the duration to a smaller value to fix the delay in the keyboard animation speed
370
+ duration: keyboardBottomOffset ? 150 : 400,
369
371
  }
370
372
  )
371
373
 
@@ -383,8 +385,8 @@ function GiftedChat<TMessage extends IMessage = IMessage> (
383
385
  focusOnInputWhenOpeningKeyboard,
384
386
  handleTextInputFocusWhenKeyboardHide,
385
387
  handleTextInputFocusWhenKeyboardShow,
386
- bottomOffset,
387
- disableKeyboardController,
388
+ keyboardBottomOffset,
389
+ isKeyboardInternallyHandled,
388
390
  ]
389
391
  )
390
392
 
@@ -398,7 +400,7 @@ function GiftedChat<TMessage extends IMessage = IMessage> (
398
400
  >
399
401
  {isInitialized
400
402
  ? (
401
- <Animated.View style={[stylesCommon.fill, (isKeyboardInternallyHandled && !disableKeyboardController) && contentStyleAnim]}>
403
+ <Animated.View style={[stylesCommon.fill, isKeyboardInternallyHandled && contentStyleAnim]}>
402
404
  {renderMessages}
403
405
  {inputToolbarFragment}
404
406
  </Animated.View>
@@ -413,14 +415,16 @@ function GiftedChat<TMessage extends IMessage = IMessage> (
413
415
  }
414
416
 
415
417
  function GiftedChatWrapper<TMessage extends IMessage = IMessage> (props: GiftedChatProps<TMessage>) {
416
- // Don't use KeyboardProvider when keyboard controller is disabled
417
- if (props.disableKeyboardController)
418
+ // Don't use KeyboardProvider when keyboard is not internally handled
419
+ if (!props.isKeyboardInternallyHandled)
418
420
  return <GiftedChat<TMessage> {...props} />
419
421
 
420
422
  return (
421
- <KeyboardProvider>
422
- <GiftedChat<TMessage> {...props} />
423
- </KeyboardProvider>
423
+ <GestureHandlerRootView style={styles.fill}>
424
+ <KeyboardProvider>
425
+ <GiftedChat<TMessage> {...props} />
426
+ </KeyboardProvider>
427
+ </GestureHandlerRootView>
424
428
  )
425
429
  }
426
430
 
@@ -1,6 +1,9 @@
1
1
  import { StyleSheet } from 'react-native'
2
2
 
3
3
  export default StyleSheet.create({
4
+ fill: {
5
+ flex: 1,
6
+ },
4
7
  contentContainer: {
5
8
  overflow: 'hidden',
6
9
  },
@@ -1,21 +1,26 @@
1
1
  import React, { RefObject } from 'react'
2
- import {
3
- ActionSheetOptions,
4
- } from '@expo/react-native-action-sheet'
5
2
  import {
6
3
  TextInput,
7
4
  StyleProp,
8
5
  TextStyle,
9
6
  ViewStyle,
10
7
  } from 'react-native'
11
- import { LightboxProps } from 'react-native-lightbox-v2'
8
+ import {
9
+ ActionSheetOptions,
10
+ } from '@expo/react-native-action-sheet'
12
11
  import { ActionsProps } from '../Actions'
13
12
  import { AvatarProps } from '../Avatar'
13
+ import { BubbleProps } from '../Bubble'
14
14
  import { ComposerProps } from '../Composer'
15
15
  import { InputToolbarProps } from '../InputToolbar'
16
16
  import { MessageProps } from '../Message'
17
+ import { AnimatedList, MessageContainerProps } from '../MessageContainer'
17
18
  import { MessageImageProps } from '../MessageImage'
18
19
  import { MessageTextProps } from '../MessageText'
20
+ import { QuickRepliesProps } from '../QuickReplies'
21
+ import { SendProps } from '../Send'
22
+ import { SystemMessageProps } from '../SystemMessage'
23
+ import { TimeProps } from '../Time'
19
24
  import {
20
25
  IMessage,
21
26
  LeftRightStyle,
@@ -23,12 +28,6 @@ import {
23
28
  MessageVideoProps,
24
29
  User,
25
30
  } from '../types'
26
- import { QuickRepliesProps } from '../QuickReplies'
27
- import { SendProps } from '../Send'
28
- import { SystemMessageProps } from '../SystemMessage'
29
- import { TimeProps } from '../Time'
30
- import { AnimatedList, MessageContainerProps } from '../MessageContainer'
31
- import { BubbleProps } from '../Bubble'
32
31
 
33
32
  export interface GiftedChatProps<TMessage extends IMessage> extends Partial<MessageContainerProps<TMessage>> {
34
33
  /* Message container ref */
@@ -54,8 +53,6 @@ export interface GiftedChatProps<TMessage extends IMessage> extends Partial<Mess
54
53
  dateFormatCalendar?: object
55
54
  /* 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` */
56
55
  isKeyboardInternallyHandled?: boolean
57
- /* Completely disable react-native-keyboard-controller. Useful when using react-native-navigation or other conflicting keyboard libraries; default is `false` */
58
- disableKeyboardController?: boolean
59
56
  /* Whether to render an avatar for the current user; default is false, only show avatars for other users */
60
57
  showUserAvatar?: boolean
61
58
  /* When false, avatars will only be displayed when a consecutive message is from the same user on the same day; default is false */
@@ -64,10 +61,8 @@ export interface GiftedChatProps<TMessage extends IMessage> extends Partial<Mess
64
61
  renderAvatarOnTop?: boolean
65
62
  /* Extra props to be passed to the <Image> component created by the default renderMessageImage */
66
63
  imageProps?: MessageImageProps<TMessage>
67
- /* Extra props to be passed to the MessageImage's Lightbox */
68
- lightboxProps?: LightboxProps
69
64
  /* Distance of the chat from the bottom of the screen (e.g. useful if you display a tab bar); default is 0 */
70
- bottomOffset?: number
65
+ keyboardBottomOffset?: number
71
66
  /* Focus on <TextInput> automatically when opening the keyboard; default is true */
72
67
  focusOnInputWhenOpeningKeyboard?: boolean
73
68
  /* Minimum height of the input toolbar; default is 44 */
@@ -148,7 +143,9 @@ export interface GiftedChatProps<TMessage extends IMessage> extends Partial<Mess
148
143
  onPressActionButton?(): void
149
144
  /* Callback when the input text changes */
150
145
  onInputTextChanged?(text: string): void
151
- /* Custom parse patterns for react-native-parsed-text used to linking message content (like URLs and phone numbers) */
146
+ /* Extra props to be passed to the MessageText component */
147
+ messageTextProps?: Partial<MessageTextProps<TMessage>>
148
+ /* Custom parse patterns for react-native-autolink used to linking message content (like URLs and phone numbers) */
152
149
  matchers?: MessageTextProps<TMessage>['matchers']
153
150
  renderQuickReplies?(
154
151
  quickReplies: QuickRepliesProps<TMessage>,