From 177df363308c09eccc071acfcd0a33d14489ff6f Mon Sep 17 00:00:00 2001 From: Paul Frazee Date: Wed, 17 May 2023 21:54:40 -0500 Subject: [PATCH] Fixes to the tab bar --- src/view/com/pager/FeedsTabBar.web.tsx | 1 - src/view/com/pager/FeedsTabBarMobile.tsx | 1 - src/view/com/pager/TabBar.tsx | 157 +++++++---------------- 3 files changed, 47 insertions(+), 112 deletions(-) diff --git a/src/view/com/pager/FeedsTabBar.web.tsx b/src/view/com/pager/FeedsTabBar.web.tsx index d1a05b15..13ee9a68 100644 --- a/src/view/com/pager/FeedsTabBar.web.tsx +++ b/src/view/com/pager/FeedsTabBar.web.tsx @@ -56,7 +56,6 @@ const FeedsTabBarDesktop = observer( {...props} key={items.join(',')} items={items} - indicatorPosition="bottom" indicatorColor={pal.colors.link} /> diff --git a/src/view/com/pager/FeedsTabBarMobile.tsx b/src/view/com/pager/FeedsTabBarMobile.tsx index 0c40da43..de3f1258 100644 --- a/src/view/com/pager/FeedsTabBarMobile.tsx +++ b/src/view/com/pager/FeedsTabBarMobile.tsx @@ -57,7 +57,6 @@ export const FeedsTabBar = observer( key={items.join(',')} {...props} items={items} - indicatorPosition="bottom" indicatorColor={pal.colors.link} /> diff --git a/src/view/com/pager/TabBar.tsx b/src/view/com/pager/TabBar.tsx index 9294b602..a04693fa 100644 --- a/src/view/com/pager/TabBar.tsx +++ b/src/view/com/pager/TabBar.tsx @@ -1,22 +1,21 @@ -import React, {createRef, useState, useMemo, useRef} from 'react' -import {Animated, StyleSheet, View, ScrollView} from 'react-native' +import React, { + useRef, + createRef, + useMemo, + useEffect, + useState, + useCallback, +} from 'react' +import {StyleSheet, View, ScrollView} from 'react-native' import {Text} from '../util/text/Text' import {PressableWithHover} from '../util/PressableWithHover' import {usePalette} from 'lib/hooks/usePalette' import {isDesktopWeb} from 'platform/detection' -interface Layout { - x: number - width: number -} - export interface TabBarProps { testID?: string selectedPage: number items: string[] - position: Animated.Value - offset: Animated.Value - indicatorPosition?: 'top' | 'bottom' indicatorColor?: string onSelect?: (index: number) => void onPressSelected?: () => void @@ -26,81 +25,27 @@ export function TabBar({ testID, selectedPage, items, - position, - offset, - indicatorPosition = 'bottom', indicatorColor, onSelect, onPressSelected, }: TabBarProps) { const pal = usePalette('default') - const [itemLayouts, setItemLayouts] = useState( - items.map(() => ({x: 0, width: 0})), - ) + const scrollElRef = useRef(null) + const [itemXs, setItemXs] = useState([]) const itemRefs = useMemo( () => Array.from({length: items.length}).map(() => createRef()), [items.length], ) - const panX = Animated.add(position, offset) - const containerRef = useRef(null) - const [scrollX, setScrollX] = useState(0) - const indicatorStyle = useMemo( - () => ({ - backgroundColor: indicatorColor || pal.colors.link, - bottom: - indicatorPosition === 'bottom' ? (isDesktopWeb ? 0 : -1) : undefined, - top: indicatorPosition === 'top' ? (isDesktopWeb ? 0 : -1) : undefined, - transform: [ - { - translateX: panX.interpolate({ - inputRange: items.map((_item, i) => i), - outputRange: itemLayouts.map(l => l.x + l.width / 2 - scrollX), - }), - }, - { - scaleX: panX.interpolate({ - inputRange: items.map((_item, i) => i), - outputRange: itemLayouts.map(l => l.width), - }), - }, - ], - }), - [ - indicatorColor, - indicatorPosition, - itemLayouts, - items, - panX, - pal.colors.link, - scrollX, - ], + () => ({borderBottomColor: indicatorColor || pal.colors.link}), + [indicatorColor, pal], ) - const onLayout = React.useCallback(() => { - const promises = [] - for (let i = 0; i < items.length; i++) { - promises.push( - new Promise(resolve => { - if (!containerRef.current || !itemRefs[i].current) { - return resolve({x: 0, width: 0}) - } + useEffect(() => { + scrollElRef.current?.scrollTo({x: itemXs[selectedPage] || 0}) + }, [scrollElRef, itemXs, selectedPage]) - itemRefs[i].current?.measureLayout( - containerRef.current, - (x: number, _y: number, width: number) => { - resolve({x, width}) - }, - ) - }), - ) - } - Promise.all(promises).then((layouts: Layout[]) => { - setItemLayouts(layouts) - }) - }, [containerRef, itemRefs, setItemLayouts, items.length]) - - const onPressItem = React.useCallback( + const onPressItem = useCallback( (index: number) => { onSelect?.(index) if (index === selectedPage) { @@ -110,28 +55,38 @@ export function TabBar({ [onSelect, onPressSelected, selectedPage], ) + const onLayout = React.useCallback(() => { + const promises = [] + for (let i = 0; i < items.length; i++) { + promises.push( + new Promise(resolve => { + if (!itemRefs[i].current) { + return resolve(0) + } + + itemRefs[i].current?.measure((x: number) => resolve(x)) + }), + ) + } + Promise.all(promises).then((Xs: number[]) => { + setItemXs(Xs) + }) + }, [itemRefs, setItemXs, items.length]) + return ( - - + { - setScrollX(nativeEvent.contentOffset.x) - }}> + ref={scrollElRef} + onLayout={onLayout}> {items.map((item, i) => { const selected = i === selectedPage return ( onPressItem(i)}>