react-native-gifted-chat 2.9.0-alpha.0 → 3.0.0-alpha.1

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 (38) hide show
  1. package/README.md +234 -319
  2. package/package.json +2 -2
  3. package/src/Avatar.tsx +12 -12
  4. package/src/Bubble/index.tsx +2 -2
  5. package/src/Bubble/types.ts +22 -22
  6. package/src/Composer.tsx +0 -3
  7. package/src/GiftedAvatar.tsx +1 -1
  8. package/src/GiftedChat/index.tsx +56 -145
  9. package/src/GiftedChat/types.ts +40 -52
  10. package/src/InputToolbar.tsx +6 -6
  11. package/src/Message/index.tsx +5 -6
  12. package/src/Message/types.ts +8 -12
  13. package/src/MessageContainer/components/DayAnimated/types.ts +1 -1
  14. package/src/MessageContainer/components/Item/index.tsx +2 -2
  15. package/src/MessageContainer/components/Item/types.ts +1 -1
  16. package/src/MessageContainer/index.tsx +30 -30
  17. package/src/MessageContainer/styles.ts +12 -5
  18. package/src/MessageContainer/types.ts +12 -16
  19. package/src/MessageImage.tsx +100 -67
  20. package/src/MessageText.tsx +1 -1
  21. package/src/Models.ts +63 -0
  22. package/src/QuickReplies.tsx +1 -1
  23. package/src/Send.tsx +30 -31
  24. package/src/SystemMessage.tsx +1 -1
  25. package/src/Time.tsx +1 -1
  26. package/src/__tests__/GiftedChat.test.tsx +0 -28
  27. package/src/__tests__/Message.test.tsx +2 -2
  28. package/src/__tests__/Send.test.tsx +1 -1
  29. package/src/__tests__/__snapshots__/Actions.test.tsx.snap +2 -86
  30. package/src/__tests__/__snapshots__/GiftedChat.test.tsx.snap +31 -54
  31. package/src/__tests__/__snapshots__/LoadEarlier.test.tsx.snap +3 -89
  32. package/src/__tests__/__snapshots__/Message.test.tsx.snap +2 -2
  33. package/src/__tests__/__snapshots__/MessageImage.test.tsx.snap +1 -1
  34. package/src/__tests__/__snapshots__/Send.test.tsx.snap +10 -142
  35. package/src/__tests__/data.ts +1 -1
  36. package/src/components/TouchableOpacity.tsx +19 -8
  37. package/src/types.ts +1 -63
  38. package/src/utils.ts +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-gifted-chat",
3
- "version": "2.9.0-alpha.0",
3
+ "version": "3.0.0-alpha.1",
4
4
  "description": "The most complete chat UI for React Native",
5
5
  "keywords": [
6
6
  "android",
@@ -94,7 +94,7 @@
94
94
  "react-dom": "19.1.0",
95
95
  "react-native": "0.81.5",
96
96
  "react-native-gesture-handler": "^2.29.1",
97
- "react-native-keyboard-controller": "^1.19.5",
97
+ "react-native-keyboard-controller": "^1.19.6",
98
98
  "react-native-reanimated": "^3.19.4",
99
99
  "react-native-safe-area-context": "^5.6.2",
100
100
  "react-test-renderer": "19.1.0",
package/src/Avatar.tsx CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  ViewStyle,
8
8
  } from 'react-native'
9
9
  import { GiftedAvatar } from './GiftedAvatar'
10
- import { IMessage, LeftRightStyle, User } from './types'
10
+ import { IMessage, LeftRightStyle, User } from './Models'
11
11
  import { isSameUser, isSameDay } from './utils'
12
12
 
13
13
  interface Styles {
@@ -57,8 +57,8 @@ export interface AvatarProps<TMessage extends IMessage> {
57
57
  previousMessage?: TMessage
58
58
  nextMessage?: TMessage
59
59
  position: 'left' | 'right'
60
- renderAvatarOnTop?: boolean
61
- showAvatarForEveryMessage?: boolean
60
+ isAvatarOnTop?: boolean
61
+ isAvatarVisibleForEveryMessage?: boolean
62
62
  imageStyle?: LeftRightStyle<ImageStyle>
63
63
  containerStyle?: LeftRightStyle<ViewStyle>
64
64
  textStyle?: TextStyle
@@ -71,8 +71,8 @@ export function Avatar<TMessage extends IMessage = IMessage> (
71
71
  props: AvatarProps<TMessage>
72
72
  ) {
73
73
  const {
74
- renderAvatarOnTop,
75
- showAvatarForEveryMessage,
74
+ isAvatarOnTop,
75
+ isAvatarVisibleForEveryMessage,
76
76
  containerStyle,
77
77
  position,
78
78
  currentMessage,
@@ -84,13 +84,13 @@ export function Avatar<TMessage extends IMessage = IMessage> (
84
84
  onLongPressAvatar,
85
85
  } = props
86
86
 
87
- const messageToCompare = renderAvatarOnTop ? previousMessage : nextMessage
87
+ const messageToCompare = isAvatarOnTop ? previousMessage : nextMessage
88
88
 
89
89
  const renderAvatarComponent = useCallback(() => {
90
90
  if (renderAvatar)
91
91
  return renderAvatar({
92
- renderAvatarOnTop,
93
- showAvatarForEveryMessage,
92
+ isAvatarOnTop,
93
+ isAvatarVisibleForEveryMessage,
94
94
  containerStyle,
95
95
  position,
96
96
  currentMessage,
@@ -117,8 +117,8 @@ export function Avatar<TMessage extends IMessage = IMessage> (
117
117
  return null
118
118
  }, [
119
119
  renderAvatar,
120
- renderAvatarOnTop,
121
- showAvatarForEveryMessage,
120
+ isAvatarOnTop,
121
+ isAvatarVisibleForEveryMessage,
122
122
  containerStyle,
123
123
  position,
124
124
  currentMessage,
@@ -133,7 +133,7 @@ export function Avatar<TMessage extends IMessage = IMessage> (
133
133
  return null
134
134
 
135
135
  if (
136
- !showAvatarForEveryMessage &&
136
+ !isAvatarVisibleForEveryMessage &&
137
137
  currentMessage &&
138
138
  messageToCompare &&
139
139
  isSameUser(currentMessage, messageToCompare) &&
@@ -159,7 +159,7 @@ export function Avatar<TMessage extends IMessage = IMessage> (
159
159
  <View
160
160
  style={[
161
161
  styles[position].container,
162
- renderAvatarOnTop && styles[position].onTop,
162
+ isAvatarOnTop && styles[position].onTop,
163
163
  containerStyle?.[position],
164
164
  ]}
165
165
  >
@@ -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.renderUsernameOnMessage && currentMessage) {
287
+ if (props.isUsernameVisible && currentMessage) {
288
288
  if (user && currentMessage.user._id === user._id)
289
289
  return null
290
290
 
@@ -6,8 +6,6 @@ import {
6
6
  } from 'react-native'
7
7
  import { MessageImageProps } from '../MessageImage'
8
8
  import { MessageTextProps } from '../MessageText'
9
- import { QuickRepliesProps } from '../QuickReplies'
10
- import { TimeProps } from '../Time'
11
9
  import {
12
10
  User,
13
11
  IMessage,
@@ -16,7 +14,9 @@ import {
16
14
  Omit,
17
15
  MessageVideoProps,
18
16
  MessageAudioProps,
19
- } from '../types'
17
+ } from '../Models'
18
+ import { QuickRepliesProps } from '../QuickReplies'
19
+ import { TimeProps } from '../Time'
20
20
 
21
21
 
22
22
  export type RenderMessageImageProps<TMessage extends IMessage> = Omit<
@@ -47,9 +47,9 @@ export type RenderMessageTextProps<TMessage extends IMessage> = Omit<
47
47
  export interface BubbleProps<TMessage extends IMessage> {
48
48
  user?: User
49
49
  touchableProps?: object
50
- renderUsernameOnMessage?: boolean
50
+ isUsernameVisible?: boolean
51
51
  isCustomViewBottom?: boolean
52
- inverted?: boolean
52
+ isInverted?: boolean
53
53
  position: 'left' | 'right'
54
54
  currentMessage: TMessage
55
55
  nextMessage?: TMessage
@@ -66,25 +66,25 @@ export interface BubbleProps<TMessage extends IMessage> {
66
66
  quickReplyTextStyle?: StyleProp<TextStyle>
67
67
  quickReplyContainerStyle?: StyleProp<ViewStyle>
68
68
  messageTextProps?: Partial<MessageTextProps<TMessage>>
69
- onPressMessage?(context?: unknown, message?: unknown): void
70
- onLongPressMessage?(context?: unknown, message?: unknown): void
71
- onQuickReply?(replies: Reply[]): void
72
- renderMessageImage?(
69
+ onPressMessage?: (context?: unknown, message?: unknown) => void
70
+ onLongPressMessage?: (context?: unknown, message?: unknown) => void
71
+ onQuickReply?: (replies: Reply[]) => void
72
+ renderMessageImage?: (
73
73
  props: RenderMessageImageProps<TMessage>,
74
- ): React.ReactNode
75
- renderMessageVideo?(
74
+ ) => React.ReactNode
75
+ renderMessageVideo?: (
76
76
  props: RenderMessageVideoProps<TMessage>,
77
- ): React.ReactNode
78
- renderMessageAudio?(
77
+ ) => React.ReactNode
78
+ renderMessageAudio?: (
79
79
  props: RenderMessageAudioProps<TMessage>,
80
- ): React.ReactNode
81
- renderMessageText?(props: RenderMessageTextProps<TMessage>): React.ReactNode
82
- renderCustomView?(bubbleProps: BubbleProps<TMessage>): React.ReactNode
83
- renderTime?(timeProps: TimeProps<TMessage>): React.ReactNode
84
- renderTicks?(currentMessage: TMessage): React.ReactNode
85
- renderUsername?(user?: TMessage['user']): React.ReactNode
86
- renderQuickReplySend?(): React.ReactNode
87
- renderQuickReplies?(
80
+ ) => React.ReactNode
81
+ renderMessageText?: (props: RenderMessageTextProps<TMessage>) => React.ReactNode
82
+ renderCustomView?: (bubbleProps: BubbleProps<TMessage>) => React.ReactNode
83
+ renderTime?: (timeProps: TimeProps<TMessage>) => React.ReactNode
84
+ renderTicks?: (currentMessage: TMessage) => React.ReactNode
85
+ renderUsername?: (user?: TMessage['user']) => React.ReactNode
86
+ renderQuickReplySend?: () => React.ReactNode
87
+ renderQuickReplies?: (
88
88
  quickReplies: QuickRepliesProps<TMessage>,
89
- ): React.ReactNode
89
+ ) => React.ReactNode
90
90
  }
package/src/Composer.tsx CHANGED
@@ -16,14 +16,12 @@ export interface ComposerProps {
16
16
  composerHeight?: number
17
17
  text?: string
18
18
  textInputProps?: Partial<TextInputProps>
19
- onTextChanged?(text: string): void
20
19
  onInputSizeChanged?(layout: { width: number, height: number }): void
21
20
  }
22
21
 
23
22
  export function Composer ({
24
23
  composerHeight = MIN_COMPOSER_HEIGHT,
25
24
  onInputSizeChanged,
26
- onTextChanged,
27
25
  text = '',
28
26
  textInputProps,
29
27
  }: ComposerProps): React.ReactElement {
@@ -67,7 +65,6 @@ export function Composer ({
67
65
  accessibilityLabel={placeholder}
68
66
  placeholderTextColor={textInputProps?.placeholderTextColor ?? (isDark ? '#888' : Color.defaultColor)}
69
67
  onContentSizeChange={handleContentSizeChange}
70
- onChangeText={onTextChanged}
71
68
  value={text}
72
69
  enablesReturnKeyAutomatically
73
70
  underlineColorAndroid='transparent'
@@ -10,8 +10,8 @@ import {
10
10
  } from 'react-native'
11
11
  import { Color } from './Color'
12
12
  import { TouchableOpacity } from './components/TouchableOpacity'
13
+ import { User } from './Models'
13
14
  import stylesCommon from './styles'
14
- import { User } from './types'
15
15
 
16
16
  const {
17
17
  carrot,
@@ -19,23 +19,14 @@ import {
19
19
  import dayjs from 'dayjs'
20
20
  import localizedFormat from 'dayjs/plugin/localizedFormat'
21
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'
22
+ import { KeyboardAvoidingView, KeyboardProvider } from 'react-native-keyboard-controller'
30
23
  import { SafeAreaProvider } from 'react-native-safe-area-context'
31
24
  import { MAX_COMPOSER_HEIGHT, MIN_COMPOSER_HEIGHT, TEST_ID } from '../Constant'
32
25
  import { GiftedChatContext } from '../GiftedChatContext'
33
26
  import { InputToolbar } from '../InputToolbar'
34
27
  import { MessageContainer, AnimatedList } from '../MessageContainer'
28
+ import { IMessage } from '../Models'
35
29
  import stylesCommon from '../styles'
36
- import {
37
- IMessage,
38
- } from '../types'
39
30
  import { renderComponentOrElement } from '../utils'
40
31
  import styles from './styles'
41
32
  import { GiftedChatProps } from './types'
@@ -63,13 +54,9 @@ function GiftedChat<TMessage extends IMessage = IMessage> (
63
54
  textInputProps,
64
55
  renderChatFooter,
65
56
  renderInputToolbar,
66
- keyboardBottomOffset = 0,
67
- focusOnInputWhenOpeningKeyboard = true,
68
- onInputTextChanged,
69
- inverted = true,
57
+ isInverted = true,
70
58
  minComposerHeight = MIN_COMPOSER_HEIGHT,
71
59
  maxComposerHeight = MAX_COMPOSER_HEIGHT,
72
- isKeyboardInternallyHandled = true,
73
60
  } = props
74
61
 
75
62
  const actionSheetRef = useRef<ActionSheetProviderRef>(null)
@@ -84,37 +71,12 @@ function GiftedChat<TMessage extends IMessage = IMessage> (
84
71
  [props.textInputRef]
85
72
  )
86
73
 
87
- const isTextInputWasFocused: RefObject<boolean> = useRef(false)
88
-
89
74
  const [isInitialized, setIsInitialized] = useState<boolean>(false)
90
75
  const [composerHeight, setComposerHeight] = useState<number>(
91
76
  minComposerHeight!
92
77
  )
93
78
  const [text, setText] = useState<string | undefined>(() => props.text || '')
94
79
 
95
- // Always call the hook, but conditionally use its data
96
- const keyboardControllerData = useReanimatedKeyboardAnimation()
97
-
98
- // Create a mock keyboard object when keyboard is not internally handled
99
- const keyboard = useMemo(() => {
100
- if (!isKeyboardInternallyHandled)
101
- return { height: { value: 0 } }
102
-
103
- return keyboardControllerData
104
- }, [isKeyboardInternallyHandled, keyboardControllerData])
105
-
106
- const trackingKeyboardMovement = useSharedValue(false)
107
- const keyboardBottomOffsetAnim = useSharedValue(0)
108
-
109
- const contentStyleAnim = useAnimatedStyle(
110
- () => ({
111
- transform: [
112
- { translateY: keyboard.height.value + keyboardBottomOffsetAnim.value },
113
- ],
114
- }),
115
- [keyboard, keyboardBottomOffsetAnim]
116
- )
117
-
118
80
  const getTextFromProp = useCallback(
119
81
  (fallback: string) => {
120
82
  if (props.text === undefined)
@@ -125,40 +87,12 @@ function GiftedChat<TMessage extends IMessage = IMessage> (
125
87
  [props.text]
126
88
  )
127
89
 
128
- /**
129
- * Store text input focus status when keyboard hide to retrieve
130
- * it afterwards if needed.
131
- * `onKeyboardWillHide` may be called twice in sequence so we
132
- * make a guard condition (eg. showing image picker)
133
- */
134
- const handleTextInputFocusWhenKeyboardHide = useCallback(() => {
135
- if (!isTextInputWasFocused.current)
136
- isTextInputWasFocused.current =
137
- textInputRef.current?.isFocused() || false
138
- }, [textInputRef])
139
-
140
- /**
141
- * Refocus the text input only if it was focused before showing keyboard.
142
- * This is needed in some cases (eg. showing image picker).
143
- */
144
- const handleTextInputFocusWhenKeyboardShow = useCallback(() => {
145
- if (
146
- textInputRef.current &&
147
- isTextInputWasFocused.current &&
148
- !textInputRef.current.isFocused()
149
- )
150
- textInputRef.current.focus()
151
-
152
- // Reset the indicator since the keyboard is shown
153
- isTextInputWasFocused.current = false
154
- }, [textInputRef])
155
-
156
90
  const scrollToBottom = useCallback(
157
91
  (isAnimated = true) => {
158
92
  if (!messageContainerRef?.current)
159
93
  return
160
94
 
161
- if (inverted) {
95
+ if (isInverted) {
162
96
  messageContainerRef.current.scrollToOffset({
163
97
  offset: 0,
164
98
  animated: isAnimated,
@@ -168,7 +102,7 @@ function GiftedChat<TMessage extends IMessage = IMessage> (
168
102
 
169
103
  messageContainerRef.current.scrollToEnd({ animated: isAnimated })
170
104
  },
171
- [inverted, messageContainerRef]
105
+ [isInverted, messageContainerRef]
172
106
  )
173
107
 
174
108
  const renderMessages = useMemo(() => {
@@ -181,7 +115,7 @@ function GiftedChat<TMessage extends IMessage = IMessage> (
181
115
  <View style={[stylesCommon.fill, messagesContainerStyle]}>
182
116
  <MessageContainer<TMessage>
183
117
  {...messagesContainerProps}
184
- inverted={inverted}
118
+ isInverted={isInverted}
185
119
  messages={messages}
186
120
  forwardRef={messageContainerRef}
187
121
  isTyping={isTyping}
@@ -194,14 +128,14 @@ function GiftedChat<TMessage extends IMessage = IMessage> (
194
128
  isTyping,
195
129
  messages,
196
130
  props,
197
- inverted,
131
+ isInverted,
198
132
  messageContainerRef,
199
133
  renderChatFooter,
200
134
  ])
201
135
 
202
136
  const notifyInputTextReset = useCallback(() => {
203
- onInputTextChanged?.('')
204
- }, [onInputTextChanged])
137
+ props.textInputProps?.onChangeText?.('')
138
+ }, [props.textInputProps])
205
139
 
206
140
  const resetInputToolbar = useCallback(() => {
207
141
  textInputRef.current?.clear()
@@ -253,15 +187,15 @@ function GiftedChat<TMessage extends IMessage = IMessage> (
253
187
  [maxComposerHeight, minComposerHeight]
254
188
  )
255
189
 
256
- const _onInputTextChanged = useCallback(
190
+ const _onChangeText = useCallback(
257
191
  (text: string) => {
258
- onInputTextChanged?.(text)
192
+ props.textInputProps?.onChangeText?.(text)
259
193
 
260
194
  // Only set state if it's not being overridden by a prop.
261
195
  if (props.text === undefined)
262
196
  setText(text)
263
197
  },
264
- [onInputTextChanged, props.text]
198
+ [props.text, props.textInputProps]
265
199
  )
266
200
 
267
201
  const onInitialLayoutViewLayout = useCallback(
@@ -293,9 +227,9 @@ function GiftedChat<TMessage extends IMessage = IMessage> (
293
227
  composerHeight: Math.max(minComposerHeight!, composerHeight),
294
228
  onSend: _onSend,
295
229
  onInputSizeChanged,
296
- onTextChanged: _onInputTextChanged,
297
230
  textInputProps: {
298
231
  ...textInputProps,
232
+ onChangeText: _onChangeText,
299
233
  ref: textInputRef,
300
234
  },
301
235
  }
@@ -316,7 +250,7 @@ function GiftedChat<TMessage extends IMessage = IMessage> (
316
250
  composerHeight,
317
251
  textInputRef,
318
252
  textInputProps,
319
- _onInputTextChanged,
253
+ _onChangeText,
320
254
  ])
321
255
 
322
256
  const contextValues = useMemo(
@@ -337,90 +271,67 @@ function GiftedChat<TMessage extends IMessage = IMessage> (
337
271
  setText(props.text)
338
272
  }, [props.text])
339
273
 
340
- // Only set up keyboard animation when keyboard is internally handled
341
- useAnimatedReaction(
342
- () => isKeyboardInternallyHandled ? keyboard.height.value : 0,
343
- (value, prevValue) => {
344
- // Skip keyboard handling when not internally handled
345
- if (!isKeyboardInternallyHandled)
346
- return
347
-
348
- if (prevValue !== null && value !== prevValue) {
349
- const isKeyboardMovingUp = value < prevValue
350
- if (isKeyboardMovingUp !== trackingKeyboardMovement.value) {
351
- trackingKeyboardMovement.value = isKeyboardMovingUp
352
- keyboardBottomOffsetAnim.value = withTiming(
353
- isKeyboardMovingUp ? keyboardBottomOffset : 0,
354
- {
355
- // If `keyboardBottomOffset` exists, we change the duration to a smaller value to fix the delay in the keyboard animation speed
356
- duration: keyboardBottomOffset ? 150 : 400,
357
- }
358
- )
359
-
360
- if (focusOnInputWhenOpeningKeyboard)
361
- if (isKeyboardMovingUp)
362
- runOnJS(handleTextInputFocusWhenKeyboardShow)()
363
- else
364
- runOnJS(handleTextInputFocusWhenKeyboardHide)()
365
- }
366
- }
367
- },
368
- [
369
- keyboard,
370
- trackingKeyboardMovement,
371
- focusOnInputWhenOpeningKeyboard,
372
- handleTextInputFocusWhenKeyboardHide,
373
- handleTextInputFocusWhenKeyboardShow,
374
- keyboardBottomOffset,
375
- isKeyboardInternallyHandled,
376
- ]
377
- )
378
-
379
274
  return (
380
275
  <GiftedChatContext.Provider value={contextValues}>
381
276
  <ActionSheetProvider ref={actionSheetRef}>
382
- <View
383
- testID={TEST_ID.WRAPPER}
384
- style={[stylesCommon.fill, styles.contentContainer]}
385
- onLayout={onInitialLayoutViewLayout}
277
+ {/* @ts-expect-error */}
278
+ <KeyboardAvoidingView
279
+ behavior='padding'
280
+ style={stylesCommon.fill}
281
+ {...props.keyboardAvoidingViewProps}
386
282
  >
387
- {isInitialized
388
- ? (
389
- <Animated.View style={[stylesCommon.fill, isKeyboardInternallyHandled && contentStyleAnim]}>
390
- {renderMessages}
391
- {inputToolbarFragment}
392
- </Animated.View>
393
- )
394
- : (
395
- renderComponentOrElement(renderLoading, {})
396
- )}
397
- </View>
283
+ <View
284
+ testID={TEST_ID.WRAPPER}
285
+ style={[stylesCommon.fill, styles.contentContainer]}
286
+ onLayout={onInitialLayoutViewLayout}
287
+ >
288
+ {isInitialized
289
+ ? (
290
+ <>
291
+ {renderMessages}
292
+ {inputToolbarFragment}
293
+ </>
294
+ )
295
+ : (
296
+ renderComponentOrElement(renderLoading, {})
297
+ )}
298
+ </View>
299
+ </KeyboardAvoidingView>
398
300
  </ActionSheetProvider>
399
301
  </GiftedChatContext.Provider>
400
302
  )
401
303
  }
402
304
 
403
305
  function GiftedChatWrapper<TMessage extends IMessage = IMessage> (props: GiftedChatProps<TMessage>) {
306
+ const {
307
+ keyboardProviderProps,
308
+ ...rest
309
+ } = props
310
+
404
311
  return (
405
- <KeyboardProvider>
406
- <GestureHandlerRootView style={styles.fill}>
407
- <SafeAreaProvider>
408
- <GiftedChat<TMessage> {...props} />
409
- </SafeAreaProvider>
410
- </GestureHandlerRootView>
411
- </KeyboardProvider>
312
+ <GestureHandlerRootView style={styles.fill}>
313
+ <SafeAreaProvider>
314
+ <KeyboardProvider
315
+ statusBarTranslucent
316
+ navigationBarTranslucent
317
+ {...keyboardProviderProps}
318
+ >
319
+ <GiftedChat<TMessage> {...rest} />
320
+ </KeyboardProvider>
321
+ </SafeAreaProvider>
322
+ </GestureHandlerRootView>
412
323
  )
413
324
  }
414
325
 
415
326
  GiftedChatWrapper.append = <TMessage extends IMessage>(
416
327
  currentMessages: TMessage[] = [],
417
328
  messages: TMessage[],
418
- inverted = true
329
+ isInverted = true
419
330
  ) => {
420
331
  if (!Array.isArray(messages))
421
332
  messages = [messages]
422
333
 
423
- return inverted
334
+ return isInverted
424
335
  ? messages.concat(currentMessages)
425
336
  : currentMessages.concat(messages)
426
337
  }
@@ -428,12 +339,12 @@ GiftedChatWrapper.append = <TMessage extends IMessage>(
428
339
  GiftedChatWrapper.prepend = <TMessage extends IMessage>(
429
340
  currentMessages: TMessage[] = [],
430
341
  messages: TMessage[],
431
- inverted = true
342
+ isInverted = true
432
343
  ) => {
433
344
  if (!Array.isArray(messages))
434
345
  messages = [messages]
435
346
 
436
- return inverted
347
+ return isInverted
437
348
  ? currentMessages.concat(messages)
438
349
  : messages.concat(currentMessages)
439
350
  }