react-native-gifted-chat 2.8.1 → 2.8.2-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +10 -5
  2. package/lib/Bubble/index.d.ts +2 -2
  3. package/lib/Bubble/index.js +8 -23
  4. package/lib/Bubble/index.js.map +1 -1
  5. package/lib/Bubble/types.d.ts +3 -3
  6. package/lib/GiftedChat/index.js +19 -4
  7. package/lib/GiftedChat/index.js.map +1 -1
  8. package/lib/GiftedChat/types.d.ts +2 -7
  9. package/lib/MessageContainer/index.js +50 -39
  10. package/lib/MessageContainer/index.js.map +1 -1
  11. package/lib/MessageContainer/styles.d.ts +3 -2
  12. package/lib/MessageContainer/styles.js +3 -2
  13. package/lib/MessageContainer/styles.js.map +1 -1
  14. package/lib/MessageContainer/types.d.ts +6 -9
  15. package/lib/MessageText.d.ts +11 -7
  16. package/lib/MessageText.js +57 -96
  17. package/lib/MessageText.js.map +1 -1
  18. package/lib/SystemMessage.d.ts +2 -1
  19. package/lib/SystemMessage.js +3 -2
  20. package/lib/SystemMessage.js.map +1 -1
  21. package/lib/utils.d.ts +2 -0
  22. package/lib/utils.js +66 -0
  23. package/lib/utils.js.map +1 -1
  24. package/package.json +33 -26
  25. package/src/Bubble/index.tsx +10 -35
  26. package/src/Bubble/types.ts +3 -3
  27. package/src/GiftedChat/index.tsx +23 -3
  28. package/src/GiftedChat/types.ts +3 -1
  29. package/src/MessageContainer/index.tsx +61 -40
  30. package/src/MessageContainer/styles.ts +3 -2
  31. package/src/MessageContainer/types.ts +6 -9
  32. package/src/MessageText.tsx +86 -121
  33. package/src/SystemMessage.tsx +4 -1
  34. package/src/__tests__/DayAnimated.test.tsx +54 -0
  35. package/src/__tests__/GiftedChat.test.tsx +25 -0
  36. package/src/__tests__/__snapshots__/DayAnimated.test.tsx.snap +5 -0
  37. package/src/__tests__/__snapshots__/GiftedChat.test.tsx.snap +25 -0
  38. package/src/__tests__/__snapshots__/MessageContainer.test.tsx.snap +10 -3
  39. package/src/utils.ts +77 -1
@@ -0,0 +1,54 @@
1
+ import 'react-native'
2
+ import React from 'react'
3
+ import renderer from 'react-test-renderer'
4
+ import DayAnimated from '../MessageContainer/components/DayAnimated'
5
+ import { DayProps } from '../Day'
6
+
7
+ const mockDaysPositions = { value: {} }
8
+ const mockScrolledY = { value: 0 }
9
+ const mockListHeight = { value: 800 }
10
+
11
+ const mockMessage = {
12
+ _id: 1,
13
+ text: 'Hello',
14
+ createdAt: new Date('2023-01-01'),
15
+ user: { _id: 1, name: 'User 1' },
16
+ }
17
+
18
+ describe('DayAnimated', () => {
19
+ it('should render DayAnimated with default Day component', () => {
20
+ const component = renderer.create(
21
+ <DayAnimated
22
+ scrolledY={mockScrolledY}
23
+ daysPositions={mockDaysPositions}
24
+ listHeight={mockListHeight}
25
+ messages={[mockMessage]}
26
+ isLoadingEarlier={false}
27
+ />
28
+ )
29
+ const tree = component.toJSON()
30
+ expect(tree).toMatchSnapshot()
31
+ })
32
+
33
+ it('should use custom renderDay when provided', () => {
34
+ const customRenderDay = jest.fn((props: DayProps) => <div data-testid='custom-day'>Custom Day: {props.createdAt}</div>)
35
+
36
+ const component = renderer.create(
37
+ <DayAnimated
38
+ scrolledY={mockScrolledY}
39
+ daysPositions={mockDaysPositions}
40
+ listHeight={mockListHeight}
41
+ messages={[mockMessage]}
42
+ isLoadingEarlier={false}
43
+ renderDay={customRenderDay}
44
+ />
45
+ )
46
+
47
+ // Force render to trigger the renderDay call if there's a createdAt
48
+ component.getInstance()
49
+
50
+ // The custom renderDay function should be available in the component
51
+ const tree = component.toJSON()
52
+ expect(tree).toMatchSnapshot()
53
+ })
54
+ })
@@ -40,3 +40,28 @@ it('should render <GiftedChat/> and compare with snapshot', () => {
40
40
 
41
41
  expect(tree.toJSON()).toMatchSnapshot()
42
42
  })
43
+
44
+ it('should render <GiftedChat/> with disableKeyboardController=true', () => {
45
+ let tree
46
+
47
+ renderer.act(() => {
48
+ (useReanimatedKeyboardAnimation as jest.Mock).mockReturnValue({
49
+ height: {
50
+ value: 0,
51
+ },
52
+ })
53
+
54
+ tree = renderer.create(
55
+ <GiftedChat
56
+ messages={messages}
57
+ onSend={() => {}}
58
+ user={{
59
+ _id: 1,
60
+ }}
61
+ disableKeyboardController={true}
62
+ />
63
+ )
64
+ })
65
+
66
+ expect(tree.toJSON()).toMatchSnapshot()
67
+ })
@@ -0,0 +1,5 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`DayAnimated should render DayAnimated with default Day component 1`] = `null`;
4
+
5
+ exports[`DayAnimated should use custom renderDay when provided 1`] = `null`;
@@ -26,3 +26,28 @@ exports[`should render <GiftedChat/> and compare with snapshot 1`] = `
26
26
  </View>
27
27
  </KeyboardProvider>
28
28
  `;
29
+
30
+ exports[`should render <GiftedChat/> with disableKeyboardController=true 1`] = `
31
+ <View
32
+ style={
33
+ {
34
+ "flex": 1,
35
+ }
36
+ }
37
+ >
38
+ <View
39
+ onLayout={[Function]}
40
+ style={
41
+ [
42
+ {
43
+ "flex": 1,
44
+ },
45
+ {
46
+ "overflow": "hidden",
47
+ },
48
+ ]
49
+ }
50
+ testID="GC_WRAPPER"
51
+ />
52
+ </View>
53
+ `;
@@ -34,6 +34,11 @@ exports[`should render <MessageContainer /> and compare with snapshot 1`] = `
34
34
  invertStickyHeaders={true}
35
35
  inverted={true}
36
36
  isInvertedVirtualizedList={true}
37
+ jestAnimatedProps={
38
+ {
39
+ "value": {},
40
+ }
41
+ }
37
42
  jestAnimatedStyle={
38
43
  {
39
44
  "value": {},
@@ -67,9 +72,11 @@ exports[`should render <MessageContainer /> and compare with snapshot 1`] = `
67
72
  },
68
73
  ],
69
74
  },
70
- {
71
- "flex": 1,
72
- },
75
+ [
76
+ {
77
+ "flex": 1,
78
+ },
79
+ ],
73
80
  ]
74
81
  }
75
82
  viewabilityConfigCallbackPairs={[]}
package/src/utils.ts CHANGED
@@ -1,5 +1,5 @@
1
+ import { useCallback, useEffect, useRef } from 'react'
1
2
  import dayjs from 'dayjs'
2
-
3
3
  import { IMessage } from './types'
4
4
 
5
5
  export function isSameDay (
@@ -29,3 +29,79 @@ export function isSameUser (
29
29
  diffMessage.user._id === currentMessage.user._id
30
30
  )
31
31
  }
32
+
33
+ function processCallbackArguments (args: unknown[]): unknown[] {
34
+ const [e, ...rest] = args
35
+ const { nativeEvent } = (e as { nativeEvent?: unknown }) || {}
36
+ let params: unknown[] = []
37
+ if (e) {
38
+ if (nativeEvent)
39
+ params.push({ nativeEvent })
40
+ else
41
+ params.push(e)
42
+ if (rest)
43
+ params = params.concat(rest)
44
+ }
45
+
46
+ return params
47
+ }
48
+
49
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
50
+ export function useCallbackDebounced<T extends (...args: any[]) => any>(callbackFunc: T, deps: React.DependencyList = [], time: number): (...args: Parameters<T>) => void {
51
+ const timeoutId = useRef<ReturnType<typeof setTimeout>>(undefined)
52
+
53
+ const savedFunc = useCallback((...args: Parameters<T>) => {
54
+ const params = processCallbackArguments(args)
55
+ if (timeoutId.current)
56
+ clearTimeout(timeoutId.current)
57
+ timeoutId.current = setTimeout(() => {
58
+ callbackFunc(...params as Parameters<T>)
59
+ }, time)
60
+ // eslint-disable-next-line react-hooks/exhaustive-deps
61
+ }, [callbackFunc, time, ...deps])
62
+
63
+ useEffect(() => {
64
+ return () => {
65
+ if (timeoutId.current)
66
+ clearTimeout(timeoutId.current)
67
+ }
68
+ }, [])
69
+
70
+ return savedFunc
71
+ }
72
+
73
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
74
+ export function useCallbackThrottled<T extends (...args: any[]) => any>(callbackFunc: T, deps: React.DependencyList = [], time: number): (...args: Parameters<T>) => void {
75
+ const lastExecution = useRef<number>(0)
76
+ const timeoutId = useRef<ReturnType<typeof setTimeout>>(undefined)
77
+
78
+ // we use function instead of arrow to access arguments object
79
+ const savedFunc = useCallback((...args: Parameters<T>) => {
80
+ const params = processCallbackArguments(args)
81
+
82
+ const now = Date.now()
83
+ const timeSinceLastExecution = now - lastExecution.current
84
+
85
+ if (timeSinceLastExecution >= time) {
86
+ // Execute immediately if enough time has passed
87
+ lastExecution.current = now
88
+ callbackFunc(...params as Parameters<T>)
89
+ } else {
90
+ // Schedule execution for the remaining time
91
+ clearTimeout(timeoutId.current)
92
+ timeoutId.current = setTimeout(() => {
93
+ lastExecution.current = Date.now()
94
+ callbackFunc(...params as Parameters<T>)
95
+ }, time - timeSinceLastExecution)
96
+ }
97
+ // eslint-disable-next-line react-hooks/exhaustive-deps
98
+ }, [callbackFunc, time, ...deps])
99
+
100
+ useEffect(() => {
101
+ return () => {
102
+ clearTimeout(timeoutId.current)
103
+ }
104
+ }, [])
105
+
106
+ return savedFunc
107
+ }