Detach syncing on tab scroll

This commit is contained in:
Dan Abramov
2023-10-16 20:35:24 +01:00
parent 828e0b0d22
commit 262125cd88
4 changed files with 28 additions and 3 deletions
+1
View File
@@ -87,6 +87,7 @@ export const FeedsTabBar = observer(function FeedsTabBarImpl(
testID={props.testID}
items={items}
dragProgress={props.dragProgress}
dragState={props.dragState}
indicatorColor={pal.colors.link}
/>
</Animated.View>
+3 -1
View File
@@ -34,6 +34,7 @@ export const Pager = forwardRef<PagerRef, React.PropsWithChildren<Props>>(
initialPage = 0,
renderTabBar,
onPageScroll,
onPageScrollStateChanged,
onPageSelected,
testID,
}: React.PropsWithChildren<Props>,
@@ -74,7 +75,8 @@ export const Pager = forwardRef<PagerRef, React.PropsWithChildren<Props>>(
style={s.h100pct}
initialPage={initialPage}
onPageSelected={onPageSelectedInner}
onPageScroll={handlePageScroll}>
onPageScroll={handlePageScroll}
onPageScrollStateChanged={onPageScrollStateChanged}>
{children}
</AnimatedPagerView>
{tabBarPosition === 'bottom' &&
+17 -2
View File
@@ -1,4 +1,4 @@
import React, {useMemo, useCallback, useState} from 'react'
import React, {useMemo, useCallback, useEffect, useState} from 'react'
import Animated, {useAnimatedReaction, useAnimatedRef, useAnimatedStyle, useDerivedValue, useSharedValue, measure, interpolate, interpolateColor, scrollTo, withSpring} from 'react-native-reanimated'
import {Dimensions, StyleSheet, View, ScrollView} from 'react-native'
import {PressableWithHover} from '../util/PressableWithHover'
@@ -22,6 +22,7 @@ const SCREEN = Dimensions.get('screen')
export function TabBar({
testID,
dragProgress,
dragState,
selectedPage,
items,
indicatorColor,
@@ -33,6 +34,7 @@ export function TabBar({
const scrollElRef = useAnimatedRef(null)
const {isDesktop, isTablet} = useWebMediaQueries()
const [layouts, setLayouts] = useState([])
const shouldSync = useSharedValue(true)
const indicatorStyle = useAnimatedStyle(() => {
if (layouts.length < items.length - 1 || layouts.some(l => l === undefined)) {
@@ -57,11 +59,21 @@ export function TabBar({
useAnimatedReaction(() => {
return (dragProgress.value / (items.length - 1)) * (contentSize.value - SCREEN.width)
}, (nextX, prevX) => {
if (prevX !== nextX) {
if (shouldSync.value && prevX !== nextX) {
scrollTo(scrollElRef, nextX, 0, false);
}
})
useAnimatedReaction(() => {
return dragState.value
}, (nextDragState, prevDragState) => {
if (nextDragState === 'idle' && nextDragState !== prevDragState) {
const nextX = (dragProgress.value / (items.length - 1)) * (contentSize.value - SCREEN.width)
scrollTo(scrollElRef, nextX, 0, true);
shouldSync.value = true
}
})
const onItemLayout = (e: LayoutChangeEvent, index: number) => {
const l = e.nativeEvent.layout
setLayouts(ls => items.map((item, i) => {
@@ -84,6 +96,9 @@ export function TabBar({
contentContainerStyle={styles.contentContainer}
onContentSizeChange={e => {
contentSize.value = e
}}
onScrollBeginDrag={e => {
shouldSync.value = false
}}>
{items.map((item, i) => {
return (
+7
View File
@@ -30,6 +30,7 @@ export const HomeScreen = withAuthRequired(
string[]
>([])
const dragProgress = useSharedValue(selectedPage)
const dragState = useSharedValue('idle')
React.useEffect(() => {
const {pinned} = store.me.savedFeeds
@@ -90,6 +91,10 @@ export const HomeScreen = withAuthRequired(
[dragProgress],
)
const onPageScrollStateChanged = React.useCallback(e => {
dragState.value = e.nativeEvent.pageScrollState
})
const onPressSelected = React.useCallback(() => {
store.emitScreenSoftReset()
}, [store])
@@ -102,6 +107,7 @@ export const HomeScreen = withAuthRequired(
selectedPage={props.selectedPage}
onSelect={props.onSelect}
dragProgress={dragProgress}
dragState={dragState}
testID="homeScreenFeedTabs"
onPressSelected={onPressSelected}
/>
@@ -124,6 +130,7 @@ export const HomeScreen = withAuthRequired(
testID="homeScreen"
onPageSelected={onPageSelected}
onPageScroll={onPageScroll}
onPageScrollStateChanged={onPageScrollStateChanged}
renderTabBar={renderTabBar}
tabBarPosition="top">
<FeedPage