Skip to content

Commit 01e116c

Browse files
committed
fix: horizontal scroll list performance issues
1 parent 2d3bf5e commit 01e116c

File tree

1 file changed

+28
-20
lines changed

1 file changed

+28
-20
lines changed

package/src/components/Message/MessageSimple/utils/renderText.tsx

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
import React, { PropsWithChildren, ReactNode, useCallback, useMemo, useRef, useState } from 'react';
1+
import React, { PropsWithChildren, ReactNode, useCallback, useMemo } from 'react';
22
import {
33
GestureResponderEvent,
44
Linking,
55
Platform,
6-
ScrollView,
76
Text,
87
TextProps,
98
View,
@@ -13,7 +12,7 @@ import {
1312
import { Gesture, GestureDetector } from 'react-native-gesture-handler';
1413
// @ts-expect-error
1514
import Markdown from 'react-native-markdown-package';
16-
import { runOnJS } from 'react-native-reanimated';
15+
import Animated, { clamp, scrollTo, useAnimatedRef, useSharedValue } from 'react-native-reanimated';
1716

1817
import {
1918
DefaultRules,
@@ -38,42 +37,51 @@ import { escapeRegExp } from '../../../../utils/utils';
3837
import type { MessageType } from '../../../MessageList/hooks/useMessageList';
3938

4039
const ReactiveScrollView = ({ children }: { children: ReactNode }) => {
41-
const [scrollViewXOffset, setScrollViewXOffset] = useState(0);
42-
const scrollViewRef = useRef<ScrollView>(null);
43-
44-
const scrollTo = useCallback((translation: number) => {
45-
if (scrollViewRef.current) {
46-
scrollViewRef.current.scrollTo({
47-
animated: false,
48-
x: translation,
49-
});
50-
}
51-
}, []);
40+
const scrollViewRef = useAnimatedRef<Animated.ScrollView>();
41+
const contentWidth = useSharedValue(0);
42+
const visibleContentWidth = useSharedValue(0);
43+
const offsetBeforeScroll = useSharedValue(0);
5244

5345
const panGesture = Gesture.Pan()
54-
.activeOffsetX([-10, 10])
46+
.activeOffsetX([-5, 5])
5547
.onUpdate((event) => {
5648
const { translationX } = event;
5749

58-
runOnJS(scrollTo)(scrollViewXOffset - translationX);
50+
scrollTo(scrollViewRef, offsetBeforeScroll.value - translationX, 0, false);
5951
})
6052
.onEnd((event) => {
6153
const { translationX } = event;
6254

63-
runOnJS(setScrollViewXOffset)(scrollViewXOffset - translationX);
55+
const velocityEffect = event.velocityX * 0.3;
56+
57+
const finalPosition = clamp(
58+
offsetBeforeScroll.value - translationX - velocityEffect,
59+
0,
60+
contentWidth.value - visibleContentWidth.value,
61+
);
62+
63+
offsetBeforeScroll.value = finalPosition;
64+
65+
scrollTo(scrollViewRef, finalPosition, 0, true);
6466
});
6567

6668
return (
6769
<GestureDetector gesture={panGesture}>
68-
<ScrollView
70+
<Animated.ScrollView
6971
contentContainerStyle={{ flexGrow: 1 }}
7072
horizontal
7173
nestedScrollEnabled={true}
74+
onContentSizeChange={(width) => {
75+
contentWidth.value = width;
76+
}}
77+
onLayout={(e) => {
78+
visibleContentWidth.value = e.nativeEvent.layout.width;
79+
}}
7280
ref={scrollViewRef}
7381
scrollEnabled={false}
7482
>
7583
{children}
76-
</ScrollView>
84+
</Animated.ScrollView>
7785
</GestureDetector>
7886
);
7987
};
@@ -560,7 +568,7 @@ const MarkdownTableColumn = ({ items, output, state, styles }: MarkdownTableRowP
560568
);
561569

562570
return (
563-
<View style={{ flexDirection: 'column', flex: 1 }}>
571+
<View style={{ flex: 1, flexDirection: 'column' }}>
564572
{headerCellContent ? (
565573
<View key={-1} style={styles.tableHeader}>
566574
<Text style={styles.tableHeaderCell}>{output(headerCellContent, state)}</Text>

0 commit comments

Comments
 (0)