react-native-gifted-chat 3.2.2 → 3.2.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-gifted-chat",
3
- "version": "3.2.2",
3
+ "version": "3.2.3",
4
4
  "description": "The most complete chat UI for React Native",
5
5
  "keywords": [
6
6
  "android",
package/src/Composer.tsx CHANGED
@@ -49,8 +49,7 @@ export function Composer ({
49
49
  const handleChange = useCallback((event: TextInputChangeEvent) => {
50
50
  if (Platform.OS === 'web')
51
51
  // Reset height to 0 to get the correct scrollHeight
52
- // @ts-expect-error - web-specific code
53
- window.requestAnimationFrame(() => {
52
+ requestAnimationFrame(() => {
54
53
  // @ts-expect-error - web-specific code
55
54
  event.nativeEvent.target.style.height = '0px'
56
55
  // @ts-expect-error - web-specific code
@@ -159,7 +159,7 @@ export function GiftedAvatar (
159
159
  if (user.avatar)
160
160
  return (
161
161
  <TouchableOpacity
162
- disabled={!onPress}
162
+ enabled={!!onPress}
163
163
  onPress={handleOnPress}
164
164
  onLongPress={handleOnLongPress}
165
165
  accessibilityRole='image'
@@ -35,7 +35,7 @@ export type MessageTextProps<TMessage extends IMessage> = {
35
35
  stripPrefix?: boolean
36
36
  }
37
37
 
38
- export const MessageText: React.FC<MessageTextProps<IMessage>> = ({
38
+ export function MessageText<TMessage extends IMessage>({
39
39
  currentMessage,
40
40
  position = 'left',
41
41
  containerStyle,
@@ -52,7 +52,7 @@ export const MessageText: React.FC<MessageTextProps<IMessage>> = ({
52
52
  hashtagUrl,
53
53
  mentionUrl,
54
54
  stripPrefix = false,
55
- }) => {
55
+ }: MessageTextProps<TMessage>) {
56
56
  const linkStyle = useMemo(() => StyleSheet.flatten([
57
57
  styles.link,
58
58
  linkStyleProp?.[position],
@@ -19,7 +19,11 @@ export const DayAnimated = ({ scrolledY, daysPositions, listHeight, renderDay, m
19
19
  const isScrolledOnMount = useSharedValue(false)
20
20
  const isLoadingAnim = useSharedValue(isLoading)
21
21
 
22
- const daysPositionsArray = useDerivedValue(() => Object.values(daysPositions.value).sort((a, b) => a.y - b.y))
22
+ const daysPositionsArray = useDerivedValue(() => Object.values(daysPositions.value).sort((a, b) => {
23
+ 'worklet'
24
+
25
+ return a.y - b.y
26
+ }))
23
27
 
24
28
  const [createdAt, setCreatedAt] = useState<number | undefined>()
25
29
 
@@ -32,28 +32,35 @@ export const useRelativeScrolledPositionToBottomOfDay = (
32
32
 
33
33
  const absoluteScrolledPositionToBottomOfDay = useAbsoluteScrolledPositionToBottomOfDay(listHeight, scrolledY, containerHeight, dayBottomMargin, dayTopOffset)
34
34
 
35
- // sorted array of days positions by y
36
- const daysPositionsArray = useDerivedValue(() => {
37
- return Object.values(daysPositions.value).sort((a, b) => {
38
- 'worklet'
39
-
40
- return a.y - b.y
41
- })
42
- })
43
-
44
35
  // find current day position by scrolled position
45
36
  const currentDayPosition = useDerivedValue(() => {
37
+ 'worklet'
38
+
39
+ // When createdAt is provided (called from AnimatedDayWrapper for a specific message),
40
+ // directly find the day position by createdAt without sorting the entire array.
41
+ // This avoids O(n log n) sorting and O(n) search for each message item.
46
42
  if (createdAt != null) {
47
- const currentDayPosition = daysPositionsArray.value.find(day => day.createdAt === createdAt)
48
- if (currentDayPosition)
49
- return currentDayPosition
43
+ const values = Object.values(daysPositions.value)
44
+ for (let i = 0; i < values.length; i++)
45
+ if (values[i].createdAt === createdAt)
46
+ return values[i]
50
47
  }
51
48
 
52
- return daysPositionsArray.value.find((day, index) => {
53
- const dayPosition = day.y + day.height
54
- return (absoluteScrolledPositionToBottomOfDay.value < dayPosition) || index === daysPositionsArray.value.length - 1
49
+ // Fallback: sort and search when createdAt is not provided (e.g., from DayAnimated)
50
+ const sortedArray = Object.values(daysPositions.value).sort((a, b) => {
51
+ 'worklet'
52
+
53
+ return a.y - b.y
55
54
  })
56
- }, [daysPositionsArray, absoluteScrolledPositionToBottomOfDay, createdAt])
55
+ for (let i = 0; i < sortedArray.length; i++) {
56
+ const day = sortedArray[i]
57
+ const dayPosition = day.y + day.height
58
+ if (absoluteScrolledPositionToBottomOfDay.value < dayPosition || i === sortedArray.length - 1)
59
+ return day
60
+ }
61
+
62
+ return undefined
63
+ }, [daysPositions, absoluteScrolledPositionToBottomOfDay, createdAt])
57
64
 
58
65
  const relativeScrolledPositionToBottomOfDay = useDerivedValue(() => {
59
66
  const scrolledBottomY = listHeight.value + scrolledY.value - (
@@ -97,13 +104,11 @@ const DayWrapper = <TMessage extends IMessage>(props: MessageProps<TMessage>) =>
97
104
  )
98
105
  }
99
106
 
100
- export const Item = <TMessage extends IMessage>(props: ItemProps<TMessage>) => {
107
+ const AnimatedDayWrapper = <TMessage extends IMessage>(props: ItemProps<TMessage>) => {
101
108
  const {
102
- renderMessage: renderMessageProp,
103
109
  scrolledY,
104
110
  daysPositions,
105
111
  listHeight,
106
- isDayAnimationEnabled,
107
112
  ...rest
108
113
  } = props
109
114
 
@@ -122,36 +127,52 @@ export const Item = <TMessage extends IMessage>(props: ItemProps<TMessage>) => {
122
127
  }, [dayContainerHeight])
123
128
 
124
129
  const style = useAnimatedStyle(() => ({
125
- opacity:
126
- isDayAnimationEnabled
127
- ? interpolate(
128
- relativeScrolledPositionToBottomOfDay.value,
129
- [
130
- -dayTopOffset,
131
- -0.0001,
132
- 0,
133
- dayContainerHeight.value + dayTopOffset,
134
- ],
135
- [
136
- 0,
137
- 0,
138
- 1,
139
- 1,
140
- ],
141
- 'clamp'
142
- )
143
- : 1,
144
- }), [relativeScrolledPositionToBottomOfDay, dayContainerHeight, dayTopOffset, isDayAnimationEnabled])
130
+ opacity: interpolate(
131
+ relativeScrolledPositionToBottomOfDay.value,
132
+ [
133
+ -dayTopOffset,
134
+ -0.0001,
135
+ 0,
136
+ dayContainerHeight.value + dayTopOffset,
137
+ ],
138
+ [
139
+ 0,
140
+ 0,
141
+ 1,
142
+ 1,
143
+ ],
144
+ 'clamp'
145
+ ),
146
+ }), [relativeScrolledPositionToBottomOfDay, dayContainerHeight, dayTopOffset])
147
+
148
+ return (
149
+ <Animated.View
150
+ style={style}
151
+ onLayout={handleLayoutDayContainer}
152
+ >
153
+ <DayWrapper<TMessage> {...rest as MessageProps<TMessage>} />
154
+ </Animated.View>
155
+ )
156
+ }
157
+
158
+ export const Item = <TMessage extends IMessage>(props: ItemProps<TMessage>) => {
159
+ const {
160
+ renderMessage: renderMessageProp,
161
+ isDayAnimationEnabled,
162
+ /* eslint-disable @typescript-eslint/no-unused-vars */
163
+ scrolledY: _scrolledY,
164
+ daysPositions: _daysPositions,
165
+ listHeight: _listHeight,
166
+ /* eslint-enable @typescript-eslint/no-unused-vars */
167
+ ...rest
168
+ } = props
145
169
 
146
170
  return (
147
171
  // do not remove key. it helps to get correct position of the day container
148
172
  <View key={props.currentMessage._id.toString()}>
149
- <Animated.View
150
- style={style}
151
- onLayout={handleLayoutDayContainer}
152
- >
153
- <DayWrapper<TMessage> {...rest as MessageProps<TMessage>} />
154
- </Animated.View>
173
+ {isDayAnimationEnabled
174
+ ? <AnimatedDayWrapper<TMessage> {...props} />
175
+ : <DayWrapper<TMessage> {...rest as MessageProps<TMessage>} />}
155
176
  {
156
177
  renderMessageProp
157
178
  ? renderMessageProp(rest as MessageProps<TMessage>)
@@ -5,12 +5,11 @@ import {
5
5
  ListRenderItemInfo,
6
6
  CellRendererProps,
7
7
  } from 'react-native'
8
- import { FlatList, Pressable, Text } from 'react-native-gesture-handler'
9
- import Animated, { runOnJS, useAnimatedScrollHandler, useAnimatedStyle, useSharedValue, withTiming } from 'react-native-reanimated'
8
+ import { Pressable, Text } from 'react-native-gesture-handler'
9
+ import Animated, { runOnJS, ScrollEvent, useAnimatedScrollHandler, useAnimatedStyle, useSharedValue, withTiming } from 'react-native-reanimated'
10
10
  import { LoadEarlierMessages } from '../LoadEarlierMessages'
11
11
  import { warning } from '../logging'
12
12
  import { IMessage } from '../Models'
13
- import { ReanimatedScrollEvent } from '../reanimatedCompat'
14
13
  import stylesCommon from '../styles'
15
14
  import { TypingIndicator } from '../TypingIndicator'
16
15
  import { isSameDay, useCallbackThrottled } from '../utils'
@@ -23,8 +22,6 @@ import { MessagesContainerProps, DaysPositions } from './types'
23
22
 
24
23
  export * from './types'
25
24
 
26
- const AnimatedFlatList = Animated.createAnimatedComponent(FlatList) as React.ComponentType<any>
27
-
28
25
  export const MessagesContainer = <TMessage extends IMessage>(props: MessagesContainerProps<TMessage>) => {
29
26
  const {
30
27
  messages = [],
@@ -114,8 +111,8 @@ export const MessagesContainer = <TMessage extends IMessage>(props: MessagesCont
114
111
  forwardRef.current.scrollToEnd({ animated })
115
112
  }, [forwardRef, isInverted, scrollTo, isScrollingDown, changeScrollToBottomVisibility])
116
113
 
117
- const handleOnScroll = useCallback((event: ReanimatedScrollEvent) => {
118
- listPropsOnScrollProp?.(event as any)
114
+ const handleOnScroll = useCallback((event: ScrollEvent) => {
115
+ listPropsOnScrollProp?.(event)
119
116
 
120
117
  const {
121
118
  contentOffset: { y: contentOffsetY },
@@ -301,6 +298,10 @@ export const MessagesContainer = <TMessage extends IMessage>(props: MessagesCont
301
298
  const handleOnLayout = (event: LayoutChangeEvent) => {
302
299
  onLayoutProp?.(event)
303
300
 
301
+ // Only track positions when day animation is enabled
302
+ if (!isDayAnimationEnabled)
303
+ return
304
+
304
305
  const { y, height } = event.nativeEvent.layout
305
306
 
306
307
  const newValue = {
@@ -343,7 +344,7 @@ export const MessagesContainer = <TMessage extends IMessage>(props: MessagesCont
343
344
  {children}
344
345
  </View>
345
346
  )
346
- }, [daysPositions, isInverted])
347
+ }, [daysPositions, isInverted, isDayAnimationEnabled])
347
348
 
348
349
  const scrollHandler = useAnimatedScrollHandler({
349
350
  onScroll: event => {
@@ -355,6 +356,10 @@ export const MessagesContainer = <TMessage extends IMessage>(props: MessagesCont
355
356
 
356
357
  // removes unrendered days positions when messages are added/removed
357
358
  useEffect(() => {
359
+ // Skip cleanup when day animation is disabled
360
+ if (!isDayAnimationEnabled)
361
+ return
362
+
358
363
  Object.keys(daysPositions.value).forEach(key => {
359
364
  const messageIndex = messages.findIndex(m => m._id.toString() === key)
360
365
  let shouldRemove = messageIndex === -1
@@ -373,7 +378,7 @@ export const MessagesContainer = <TMessage extends IMessage>(props: MessagesCont
373
378
  return value
374
379
  })
375
380
  })
376
- }, [messages, daysPositions, isInverted])
381
+ }, [messages, daysPositions, isInverted, isDayAnimationEnabled])
377
382
 
378
383
  return (
379
384
  <View
@@ -382,7 +387,7 @@ export const MessagesContainer = <TMessage extends IMessage>(props: MessagesCont
382
387
  isAlignedTop ? styles.containerAlignTop : stylesCommon.fill,
383
388
  ]}
384
389
  >
385
- <AnimatedFlatList
390
+ <Animated.FlatList
386
391
  ref={forwardRef}
387
392
  keyExtractor={keyExtractor}
388
393
  data={messages}
@@ -390,6 +395,7 @@ export const MessagesContainer = <TMessage extends IMessage>(props: MessagesCont
390
395
  inverted={isInverted}
391
396
  automaticallyAdjustContentInsets={false}
392
397
  style={stylesCommon.fill}
398
+ contentContainerStyle={styles.messagesContainer}
393
399
  ListEmptyComponent={renderChatEmpty}
394
400
  ListFooterComponent={
395
401
  isInverted ? ListHeaderComponent : ListFooterComponent
@@ -9,6 +9,8 @@ export default StyleSheet.create({
9
9
  contentContainerStyle: {
10
10
  flexGrow: 1,
11
11
  justifyContent: 'flex-start',
12
+ },
13
+ messagesContainer: {
12
14
  paddingBottom: 10,
13
15
  },
14
16
  emptyChatContainer: {
@@ -1,10 +1,10 @@
1
- import React, { RefObject } from 'react'
1
+ import { RefObject } from 'react'
2
2
  import {
3
3
  FlatListProps,
4
4
  StyleProp,
5
5
  ViewStyle,
6
6
  } from 'react-native'
7
- import { FlatList } from 'react-native-gesture-handler'
7
+ import Animated, { AnimatedProps, ScrollEvent } from 'react-native-reanimated'
8
8
 
9
9
  import { DayProps } from '../Day'
10
10
  import { LoadEarlierMessagesProps } from '../LoadEarlierMessages'
@@ -12,9 +12,13 @@ import { MessageProps } from '../Message'
12
12
  import { User, IMessage, Reply } from '../Models'
13
13
  import { TypingIndicatorProps } from '../TypingIndicator/types'
14
14
 
15
- export type ListProps<TMessage extends IMessage = IMessage> = Partial<FlatListProps<TMessage>>
15
+ export type AnimatedListProps<TMessage extends IMessage = IMessage> = Partial<
16
+ Omit<AnimatedProps<FlatListProps<TMessage>>, 'onScroll'> & {
17
+ onScroll?: (event: ScrollEvent) => void
18
+ }
19
+ >
16
20
 
17
- export type AnimatedList<TMessage> = FlatList<TMessage>
21
+ export type AnimatedList<TMessage> = Animated.FlatList<TMessage>
18
22
 
19
23
  export interface MessagesContainerProps<TMessage extends IMessage = IMessage>
20
24
  extends Omit<TypingIndicatorProps, 'style'> {
@@ -25,7 +29,7 @@ export interface MessagesContainerProps<TMessage extends IMessage = IMessage>
25
29
  /** User sending the messages: { _id, name, avatar } */
26
30
  user?: User
27
31
  /** Additional props for FlatList */
28
- listProps?: ListProps<TMessage>
32
+ listProps?: AnimatedListProps<TMessage>
29
33
  /** Reverses display order of messages; default is true */
30
34
  isInverted?: boolean
31
35
  /** Controls whether or not the message bubbles appear at the top of the chat */
@@ -32,34 +32,39 @@ export function SystemMessage<TMessage extends IMessage> ({
32
32
  return null
33
33
 
34
34
  return (
35
- <View style={[stylesCommon.fill, styles.container, containerStyle]}>
36
- {
37
- !!currentMessage.text && (
38
- <MessageText
39
- currentMessage={currentMessage}
40
- customTextStyle={[styles.text, textStyle]}
41
- position='left'
42
- containerStyle={{ left: [styles.messageContainer, messageContainerStyle] }}
43
- {...messageTextProps}
44
- />
45
- )
46
- }
47
- {children}
35
+ <View style={[stylesCommon.fill, styles.wrapper]}>
36
+ <View style={[styles.container, containerStyle]}>
37
+ {
38
+ !!currentMessage.text && (
39
+ <MessageText
40
+ currentMessage={currentMessage}
41
+ customTextStyle={[styles.text, textStyle]}
42
+ position='left'
43
+ containerStyle={{ left: [styles.messageContainer, messageContainerStyle] }}
44
+ {...messageTextProps}
45
+ />
46
+ )
47
+ }
48
+ {children}
49
+ </View>
48
50
  </View>
49
51
  )
50
52
  }
51
53
 
52
54
  const styles = StyleSheet.create({
55
+ wrapper: {
56
+ alignItems: 'center',
57
+ marginVertical: 5,
58
+ marginHorizontal: 10,
59
+ },
53
60
  container: {
61
+ maxWidth: '70%',
54
62
  borderRadius: 20,
55
63
  borderWidth: 1,
56
64
  borderColor: 'rgba(0,0,0,0.1)',
57
65
  paddingHorizontal: 10,
58
66
  paddingVertical: 10,
59
67
  backgroundColor: 'rgba(0,0,0,0.05)',
60
- marginVertical: 5,
61
- marginHorizontal: 10,
62
- alignItems: 'flex-end',
63
68
  },
64
69
  messageContainer: {
65
70
  marginVertical: 0,
@@ -69,5 +74,6 @@ const styles = StyleSheet.create({
69
74
  backgroundColor: Color.backgroundTransparent,
70
75
  fontSize: 12,
71
76
  fontWeight: '300',
77
+ textAlign: 'center',
72
78
  },
73
79
  })
@@ -10,17 +10,10 @@ exports[`SystemMessage should render <SystemMessage /> and compare with snapshot
10
10
  "flex": 1,
11
11
  },
12
12
  {
13
- "alignItems": "flex-end",
14
- "backgroundColor": "rgba(0,0,0,0.05)",
15
- "borderColor": "rgba(0,0,0,0.1)",
16
- "borderRadius": 20,
17
- "borderWidth": 1,
13
+ "alignItems": "center",
18
14
  "marginHorizontal": 10,
19
15
  "marginVertical": 5,
20
- "paddingHorizontal": 10,
21
- "paddingVertical": 10,
22
16
  },
23
- undefined,
24
17
  ]
25
18
  }
26
19
  >
@@ -28,39 +21,57 @@ exports[`SystemMessage should render <SystemMessage /> and compare with snapshot
28
21
  style={
29
22
  [
30
23
  {
31
- "marginHorizontal": 10,
32
- "marginVertical": 5,
24
+ "backgroundColor": "rgba(0,0,0,0.05)",
25
+ "borderColor": "rgba(0,0,0,0.1)",
26
+ "borderRadius": 20,
27
+ "borderWidth": 1,
28
+ "maxWidth": "70%",
29
+ "paddingHorizontal": 10,
30
+ "paddingVertical": 10,
33
31
  },
34
- [
35
- {
36
- "marginHorizontal": 0,
37
- "marginVertical": 0,
38
- },
39
- undefined,
40
- ],
32
+ undefined,
41
33
  ]
42
34
  }
43
35
  >
44
- <Text
36
+ <View
45
37
  style={
46
38
  [
47
39
  {
48
- "color": "black",
40
+ "marginHorizontal": 10,
41
+ "marginVertical": 5,
49
42
  },
50
- undefined,
51
43
  [
52
44
  {
53
- "backgroundColor": "transparent",
54
- "fontSize": 12,
55
- "fontWeight": "300",
45
+ "marginHorizontal": 0,
46
+ "marginVertical": 0,
56
47
  },
57
48
  undefined,
58
49
  ],
59
50
  ]
60
51
  }
61
52
  >
62
- test
63
- </Text>
53
+ <Text
54
+ style={
55
+ [
56
+ {
57
+ "color": "black",
58
+ },
59
+ undefined,
60
+ [
61
+ {
62
+ "backgroundColor": "transparent",
63
+ "fontSize": 12,
64
+ "fontWeight": "300",
65
+ "textAlign": "center",
66
+ },
67
+ undefined,
68
+ ],
69
+ ]
70
+ }
71
+ >
72
+ test
73
+ </Text>
74
+ </View>
64
75
  </View>
65
76
  </View>
66
77
  `;
package/CHANGELOG.md DELETED
@@ -1,364 +0,0 @@
1
- # Changelog
2
-
3
- ## [3.2.0] - 2025-11-25
4
-
5
- ### ✨ Features
6
- - **Custom Link Parser**: Replaced `react-native-autolink` dependency with custom link parser implementation for better control and performance
7
- - Removed external dependency on `react-native-autolink`
8
- - Improved link parsing with custom implementation in `linkParser.tsx`
9
- - Updated `MessageText` component to use new parser
10
- - Enhanced links example in example app
11
-
12
- ### 🐛 Bug Fixes
13
- - Adjusted message bubble styles for better rendering
14
- - Updated test snapshots to reflect parser changes
15
-
16
- ## [3.1.5] - 2025-11-25
17
-
18
- ### ✨ Features
19
- - **Color Scheme Support**: Added `colorScheme` prop to `GiftedChat` component
20
- - New `useColorScheme` hook for consistent color scheme handling
21
- - Automatically adapts UI elements (Composer, InputToolbar, Send) based on color scheme
22
- - Added comprehensive tests for color scheme functionality
23
-
24
- ### 📝 Documentation
25
- - Updated README with `colorScheme` prop documentation
26
-
27
- ## [3.1.4] - 2025-11-25
28
-
29
- ### 🐛 Bug Fixes
30
- - Added left padding to `TextInput` when no accessory is present for better visual alignment
31
- - Adjusted input toolbar styles for improved layout
32
-
33
- ## [3.1.3] - 2025-11-25
34
-
35
- ### 🔧 Improvements
36
- - Removed unused imports for cleaner codebase
37
-
38
- ## [3.1.2] - 2025-11-24
39
-
40
- ### 🐛 Bug Fixes
41
- - Fixed message bubble styles for small messages
42
- - Improved rendering of compact message content
43
-
44
- ### 🧪 Testing
45
- - Updated test snapshots
46
-
47
- ## [3.1.1] - 2025-11-24
48
-
49
- ### 🐛 Bug Fixes
50
- - Fixed Bubble component styles for better message rendering
51
- - Corrected style inconsistencies in message bubbles
52
-
53
- ### 🧪 Testing
54
- - Updated test snapshots to reflect style fixes
55
-
56
- ## [3.1.0] - 2025-11-24
57
-
58
- ### 🔧 Improvements
59
- - Refactored component styles for better maintainability
60
- - Updated Expo Snack example with latest changes
61
-
62
- ### 🧪 Testing
63
- - Updated test snapshots
64
-
65
- ## [3.0.1] - 2025-11-24
66
-
67
- ### 🐛 Bug Fixes
68
- - Fixed Composer auto-resize height behavior on web platform
69
-
70
- ### 🧪 Testing
71
- - Updated test snapshots
72
-
73
- ## [3.0.0] - 2025-11-23
74
-
75
- This is a major release with significant breaking changes, new features, and improvements. The library has been completely rewritten in TypeScript with improved type safety, better keyboard handling, and enhanced customization options.
76
-
77
- ### 🚨 Breaking Changes
78
-
79
- #### Renamed Props (GiftedChat)
80
- - `onInputTextChanged` → moved to `textInputProps.onChangeText` (follows React Native naming pattern)
81
- - `alwaysShowSend` → `isSendButtonAlwaysVisible` (consistent boolean naming convention)
82
- - `onPress` → `onPressMessage` (more specific naming)
83
- - `onLongPress` → `onLongPressMessage` (more specific naming)
84
- - `options` → `actions` (better semantic naming, different type signature)
85
- - `optionTintColor` → `actionSheetOptionTintColor` (clearer naming)
86
- - `renderUsernameOnMessage` → `isUsernameVisible` (consistent boolean naming)
87
- - `showUserAvatar` → `isUserAvatarVisible` (consistent boolean naming)
88
- - `showAvatarForEveryMessage` → `isAvatarVisibleForEveryMessage` (consistent boolean naming)
89
- - `renderAvatarOnTop` → `isAvatarOnTop` (consistent boolean naming)
90
- - `focusOnInputWhenOpeningKeyboard` → `shouldFocusInputOnKeyboardOpen` (consistent boolean naming)
91
- - `messageContainerRef` → `messagesContainerRef` (typo fix)
92
- - `alignTop` → `isAlignedTop` (consistent boolean naming)
93
- - `inverted` → `isInverted` (consistent boolean naming)
94
-
95
- #### Removed Props (GiftedChat)
96
- - `bottomOffset` - use `keyboardAvoidingViewProps.keyboardVerticalOffset` instead
97
- - `disableKeyboardController` - removed keyboard controller configuration
98
- - `isKeyboardInternallyHandled` - keyboard handling now always uses react-native-keyboard-controller
99
- - `lightboxProps` - custom Modal implementation replaced react-native-lightbox-v2
100
- - `placeholder` - moved to `textInputProps.placeholder`
101
- - `disableComposer` - moved to `textInputProps.editable={false}`
102
- - `keyboardShouldPersistTaps` - moved to `listProps.keyboardShouldPersistTaps`
103
- - `maxInputLength` - moved to `textInputProps.maxLength`
104
- - `extraData` - moved to `listProps.extraData`
105
- - `infiniteScroll` - use `loadEarlierMessagesProps.isInfiniteScrollEnabled` instead
106
- - `parsePatterns` - removed, automatic link parsing improved
107
-
108
- #### Props Moved to MessagesContainer (via spreading)
109
- These props moved from `GiftedChatProps` to `MessagesContainerProps` but are still accessible on `GiftedChat` via prop spreading:
110
- - `messages` - now in MessagesContainerProps
111
- - `isTyping` - now in MessagesContainerProps (via TypingIndicatorProps)
112
- - `loadEarlier` → `loadEarlierMessagesProps.isAvailable`
113
- - `isLoadingEarlier` → `loadEarlierMessagesProps.isLoading`
114
- - `onLoadEarlier` → `loadEarlierMessagesProps.onPress`
115
- - `renderLoadEarlier` - now in MessagesContainerProps
116
- - `renderDay` - now in MessagesContainerProps
117
- - `renderMessage` - now in MessagesContainerProps
118
- - `renderFooter` - now in MessagesContainerProps
119
- - `renderChatEmpty` - now in MessagesContainerProps
120
- - `scrollToBottomStyle` - now in MessagesContainerProps
121
- - `isScrollToBottomEnabled` - now in MessagesContainerProps
122
- - `scrollToBottomComponent` - now in MessagesContainerProps
123
- - `onQuickReply` - now in MessagesContainerProps
124
- - `listViewProps` → `listProps` (renamed in MessagesContainerProps)
125
-
126
- #### Type Signature Changes
127
- - `options`: changed from `{ [key: string]: () => void }` to `Array<{ title: string, action: () => void }>`
128
- - `textInputProps`: changed from `object` to `Partial<React.ComponentProps<typeof TextInput>>`
129
- - `renderInputToolbar`: now accepts `React.ComponentType | React.ReactElement | function | null` (can be component, element, function, or null)
130
- - All callback props now use arrow function syntax instead of function syntax for better type inference
131
-
132
- #### Dependency Changes
133
- - Removed `react-native-lightbox-v2` (replaced with custom Modal implementation)
134
- - Removed `react-native-iphone-x-helper` (deprecated)
135
- - Removed `react-native-keyboard-controller` as direct dependency
136
- - Added `react-native-keyboard-controller` as peer dependency (>=1.0.0)
137
- - Added `react-native-gesture-handler` as peer dependency (>=2.0.0)
138
- - Added `react-native-reanimated` support for v3 & v4
139
- - Added `react-native-safe-area-context` as peer dependency (>=5.0.0)
140
-
141
- ### ✨ New Features
142
-
143
- #### TypeScript Migration
144
- - Complete conversion from JavaScript to TypeScript/TSX
145
- - Improved type safety and IntelliSense support
146
- - Better type definitions for all components and props
147
- - Refactored types to arrow functions for better readability
148
-
149
- #### Keyboard Handling
150
- - New `keyboardTopToolbarHeight` prop for better keyboard customization
151
- - New `keyboardAvoidingViewProps` to pass props to KeyboardAvoidingView from react-native-keyboard-controller
152
- - Improved keyboard behavior and offset handling
153
- - Consolidated keyboard configuration (removed individual keyboard props in favor of `keyboardAvoidingViewProps`)
154
- - Fixed auto-grow text input behavior
155
- - Better keyboard open/close transitions
156
- - New `OverKeyboardView` component for MessageImage to keep keyboard open
157
-
158
- #### Message Rendering
159
- - `isDayAnimationEnabled` prop to control day separator animations
160
- - Support for passing custom components in render functions
161
- - Improved message parsing with better link detection
162
- - Parse links in system messages (fixes #2105)
163
- - Better phone number parsing with custom matchers support
164
- - Improved URL parsing (email, phone, URL detection)
165
-
166
- #### UI & Styling
167
- - Dark theme support in example app
168
- - Safe area provider included in library
169
- - Improved LoadEarlier messages logic
170
- - Better themed styles implementation
171
- - Fixed press animation for TouchableOpacity
172
- - Replaced deprecated `TouchableWithoutFeedback` with `Pressable`
173
- - Better scroll to bottom button behavior on Android
174
-
175
- #### Image Viewing
176
- - Custom Modal implementation replacing react-native-lightbox-v2
177
- - Better image viewing experience with proper insets handling
178
- - Improved MessageImage component
179
-
180
- #### Accessibility & UX
181
- - `renderTicks` prop for message status indicators
182
- - Better scroll to bottom wrapper visibility handling
183
- - `useCallbackThrottled` for improved scroll performance
184
- - Allow passing children to SystemMessage
185
- - Improved load earlier messages functionality
186
-
187
- ### 🐛 Bug Fixes
188
-
189
- - Fixed duplicate paragraph tags in README
190
- - Fixed scroll to bottom when `isScrollToBottomEnabled=false` (#2652)
191
- - Fixed TypeScript type inconsistencies and ESLint errors (#2653)
192
- - Fixed automatic scroll to bottom issues (#2630, #2621, #2644)
193
- - Fixed DayAnimated test import and added proper test coverage for renderDay prop
194
- - Fixed not passed `isDayAnimationEnabled` prop
195
- - Fixed MessageContainer scroll to bottom press on Android
196
- - Fixed safer change ScrollToBottomWrapper visibility
197
- - Fixed dependency cycles in imports
198
- - Fixed MessageText container style
199
- - Fixed reanimated issue in MessageContainer
200
- - Fixed construct messages on send in example
201
- - Fixed web support in example
202
- - Fixed #2659 (memoization issues)
203
- - Fixed #2640 (various bug fixes)
204
- - Fixed show location in example
205
- - Fixed errors in keyboard handling
206
- - Fixed load earlier messages functionality
207
- - Fixed Bubble type parameter to re-enable generics on message prop (#2639)
208
- - Fixed listViewProps typing with Partial<FlatListProps> (#2628)
209
- - Fixed MessageContainer to add renderDay prop and insert DayAnimated Component (#2632)
210
- - Fixed dateFormatCalendar default value in README
211
-
212
- ### 🔧 Improvements
213
-
214
- #### Performance
215
- - Memoized values & functions for better performance
216
- - Better scroll performance with throttled callbacks
217
- - Optimized re-renders
218
-
219
- #### Code Quality
220
- - Added ESLint with import sorting
221
- - Fixed all examples with ESLint
222
- - Improved code structure and organization
223
- - Better error handling
224
- - Cleaner prop passing and component structure
225
-
226
- #### Testing
227
- - All tests converted to TypeScript
228
- - Updated snapshots for new components
229
- - Run tests in correct timezone (Europe/Paris)
230
- - Improved test coverage
231
- - Added comprehensive copilot instructions with validated commands
232
-
233
- #### Documentation
234
- - Improved README structure and formatting
235
- - Better prop documentation and grouping
236
- - Added matchers example
237
- - Added working Expo Snack link
238
- - Better feature documentation
239
- - Added maintainer section
240
- - Improved previews and images
241
- - Added export documentation
242
- - Fixed formatting issues and typos
243
- - Better keyboard props documentation
244
-
245
- #### Example App
246
- - Updated to latest React Native and Expo
247
- - Added tabs with different chat examples
248
- - Added working link to Expo Snack
249
- - Better example organization
250
- - Added dark theme support
251
- - Removed padding from bottom of toolbar
252
- - Added custom phone matcher example
253
- - Switch to dev build in README
254
- - Android: transparent navigation & status bars by default
255
- - Better project structure with multiple example types
256
-
257
- #### Build & Development
258
- - Better dependency management
259
- - Updated to Node.js >= 20
260
- - Yarn 1.22.22+ as package manager
261
- - Added stale workflow for issue management
262
- - Script to rebuild native dependencies
263
- - Improved local development setup
264
-
265
- ### 📦 Dependencies
266
-
267
- #### Added
268
- - `@expo/react-native-action-sheet`: ^4.1.1
269
- - `@types/lodash.isequal`: ^4.5.8
270
- - `dayjs`: ^1.11.19
271
- - `lodash.isequal`: ^4.5.0
272
- - `react-native-zoom-reanimated`: ^1.4.10
273
-
274
- #### Peer Dependencies (now required)
275
- - `react`: >=18.0.0
276
- - `react-native`: *
277
- - `react-native-gesture-handler`: >=2.0.0
278
- - `react-native-keyboard-controller`: >=1.0.0
279
- - `react-native-reanimated`: >=3.0.0 || ^4.0.0
280
- - `react-native-safe-area-context`: >=5.0.0
281
-
282
- ### 🔄 Migration Guide
283
-
284
- #### Update Prop Names
285
- ```javascript
286
- // Before (v2.8.1)
287
- <GiftedChat
288
- messages={messages}
289
- onInputTextChanged={handleTextChange}
290
- alwaysShowSend={true}
291
- onPress={handlePress}
292
- onLongPress={handleLongPress}
293
- options={{ 'Option 1': action1, 'Option 2': action2 }}
294
- optionTintColor="#007AFF"
295
- bottomOffset={100}
296
- placeholder="Type a message..."
297
- maxInputLength={1000}
298
- renderUsernameOnMessage={true}
299
- showUserAvatar={false}
300
- showAvatarForEveryMessage={false}
301
- renderAvatarOnTop={false}
302
- alignTop={false}
303
- inverted={true}
304
- loadEarlier={true}
305
- isLoadingEarlier={false}
306
- onLoadEarlier={handleLoadEarlier}
307
- />
308
-
309
- // After (v3.0.0)
310
- <GiftedChat
311
- messages={messages}
312
- textInputProps={{
313
- onChangeText: handleTextChange,
314
- placeholder: "Type a message...",
315
- maxLength: 1000
316
- }}
317
- isSendButtonAlwaysVisible={true}
318
- onPressMessage={handlePress}
319
- onLongPressMessage={handleLongPress}
320
- actions={[
321
- { title: 'Option 1', action: action1 },
322
- { title: 'Option 2', action: action2 }
323
- ]}
324
- actionSheetOptionTintColor="#007AFF"
325
- keyboardAvoidingViewProps={{ keyboardVerticalOffset: 100 }}
326
- isUsernameVisible={true}
327
- isUserAvatarVisible={false}
328
- isAvatarVisibleForEveryMessage={false}
329
- isAvatarOnTop={false}
330
- isAlignedTop={false}
331
- isInverted={true}
332
- loadEarlierMessagesProps={{
333
- isAvailable: true,
334
- isLoading: false,
335
- onPress: handleLoadEarlier
336
- }}
337
- />
338
- ```
339
-
340
- #### Install Peer Dependencies
341
- ```bash
342
- npm install react-native-gesture-handler react-native-keyboard-controller react-native-reanimated react-native-safe-area-context
343
- # or
344
- yarn add react-native-gesture-handler react-native-keyboard-controller react-native-reanimated react-native-safe-area-context
345
- ```
346
-
347
- #### Update Image Lightbox
348
- The library now uses a custom Modal implementation instead of react-native-lightbox-v2. If you were customizing the lightbox, you'll need to update your customization approach.
349
-
350
- ### 📝 Notes
351
-
352
- - This version includes 170+ commits since v2.8.1
353
- - Full TypeScript support with improved type definitions
354
- - Better React Native compatibility (tested with RN 0.81.5)
355
- - Improved React 19 support
356
- - Better Expo integration
357
-
358
- ### 👥 Contributors
359
-
360
- Special thanks to all contributors who made this release possible, including fixes and improvements from the community.
361
-
362
- ---
363
-
364
- For detailed commit history, see: https://github.com/FaridSafi/react-native-gifted-chat/compare/2.8.1...3.0.0
@@ -1,27 +0,0 @@
1
- /**
2
- * Compatibility layer for react-native-reanimated v3 and v4
3
- *
4
- * In v3, types are exported from 'react-native-reanimated/lib/typescript/hook/commonTypes'
5
- * In v4, the type structure changed - we define a compatible type that works with both
6
- */
7
-
8
- import type { NativeScrollEvent } from 'react-native'
9
-
10
- /**
11
- * Compatible type for scroll events from useAnimatedScrollHandler
12
- * Works with both react-native-reanimated v3 and v4
13
- */
14
- export type ReanimatedScrollEvent = Readonly<{
15
- contentOffset: {
16
- x: number
17
- y: number
18
- }
19
- contentSize: {
20
- height: number
21
- width: number
22
- }
23
- layoutMeasurement: {
24
- height: number
25
- width: number
26
- }
27
- }> & Readonly<NativeScrollEvent>