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