react-native-gifted-chat 2.8.0 → 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.
- package/README.md +18 -5
- package/lib/Bubble/index.d.ts +3 -27
- package/lib/Bubble/index.js +138 -125
- package/lib/Bubble/index.js.map +1 -1
- package/lib/Bubble/types.d.ts +3 -3
- package/lib/GiftedChat/index.js +19 -4
- package/lib/GiftedChat/index.js.map +1 -1
- package/lib/GiftedChat/types.d.ts +5 -10
- package/lib/Message/index.js +7 -12
- package/lib/Message/index.js.map +1 -1
- package/lib/Message/types.d.ts +2 -2
- package/lib/MessageContainer/components/Item/index.js +3 -1
- package/lib/MessageContainer/components/Item/index.js.map +1 -1
- package/lib/MessageContainer/index.js +69 -46
- package/lib/MessageContainer/index.js.map +1 -1
- package/lib/MessageContainer/styles.d.ts +3 -2
- package/lib/MessageContainer/styles.js +3 -2
- package/lib/MessageContainer/styles.js.map +1 -1
- package/lib/MessageContainer/types.d.ts +6 -9
- package/lib/MessageText.d.ts +11 -7
- package/lib/MessageText.js +57 -96
- package/lib/MessageText.js.map +1 -1
- package/lib/SystemMessage.d.ts +2 -1
- package/lib/SystemMessage.js +3 -2
- package/lib/SystemMessage.js.map +1 -1
- package/lib/utils.d.ts +2 -0
- package/lib/utils.js +66 -0
- package/lib/utils.js.map +1 -1
- package/package.json +37 -30
- package/src/Bubble/index.tsx +171 -172
- package/src/Bubble/types.ts +3 -3
- package/src/GiftedChat/index.tsx +23 -3
- package/src/GiftedChat/types.ts +6 -4
- package/src/Message/index.tsx +10 -16
- package/src/Message/types.ts +2 -2
- package/src/MessageContainer/components/Item/index.tsx +1 -0
- package/src/MessageContainer/index.tsx +93 -58
- package/src/MessageContainer/styles.ts +3 -2
- package/src/MessageContainer/types.ts +6 -9
- package/src/MessageText.tsx +86 -121
- package/src/SystemMessage.tsx +4 -1
- package/src/__tests__/DayAnimated.test.tsx +54 -0
- package/src/__tests__/GiftedChat.test.tsx +25 -0
- package/src/__tests__/__snapshots__/DayAnimated.test.tsx.snap +5 -0
- package/src/__tests__/__snapshots__/GiftedChat.test.tsx.snap +25 -0
- package/src/__tests__/__snapshots__/MessageContainer.test.tsx.snap +11 -9
- 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
|
+
})
|
|
@@ -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
|
+
`;
|
|
@@ -28,17 +28,17 @@ exports[`should render <MessageContainer /> and compare with snapshot 1`] = `
|
|
|
28
28
|
automaticallyAdjustContentInsets={false}
|
|
29
29
|
collapsable={false}
|
|
30
30
|
data={[]}
|
|
31
|
-
extraData={
|
|
32
|
-
[
|
|
33
|
-
null,
|
|
34
|
-
false,
|
|
35
|
-
]
|
|
36
|
-
}
|
|
31
|
+
extraData={null}
|
|
37
32
|
getItem={[Function]}
|
|
38
33
|
getItemCount={[Function]}
|
|
39
34
|
invertStickyHeaders={true}
|
|
40
35
|
inverted={true}
|
|
41
36
|
isInvertedVirtualizedList={true}
|
|
37
|
+
jestAnimatedProps={
|
|
38
|
+
{
|
|
39
|
+
"value": {},
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
42
|
jestAnimatedStyle={
|
|
43
43
|
{
|
|
44
44
|
"value": {},
|
|
@@ -72,9 +72,11 @@ exports[`should render <MessageContainer /> and compare with snapshot 1`] = `
|
|
|
72
72
|
},
|
|
73
73
|
],
|
|
74
74
|
},
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
75
|
+
[
|
|
76
|
+
{
|
|
77
|
+
"flex": 1,
|
|
78
|
+
},
|
|
79
|
+
],
|
|
78
80
|
]
|
|
79
81
|
}
|
|
80
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
|
+
}
|