diff options
author | dan <dan.abramov@gmail.com> | 2023-12-05 17:13:09 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-12-05 09:13:09 -0800 |
commit | ed5a97d0fab249cab91539f0c4dc7d3084bc59a8 (patch) | |
tree | ee4f859aaa4fa11f94a66d7d7af36290184afd25 /src | |
parent | 37d94ca0e3e75e73a856bd4dad37d57cfaeadf1d (diff) | |
download | voidsky-ed5a97d0fab249cab91539f0c4dc7d3084bc59a8.tar.zst |
Fix jump when toggling suggestions (#2090)
Diffstat (limited to 'src')
-rw-r--r-- | src/view/com/pager/PagerWithHeader.tsx | 6 | ||||
-rw-r--r-- | src/view/com/profile/ProfileHeader.tsx | 12 | ||||
-rw-r--r-- | src/view/com/profile/ProfileHeaderSuggestedFollows.tsx | 156 |
3 files changed, 74 insertions, 100 deletions
diff --git a/src/view/com/pager/PagerWithHeader.tsx b/src/view/com/pager/PagerWithHeader.tsx index dcfc1eebb..22e2d86b1 100644 --- a/src/view/com/pager/PagerWithHeader.tsx +++ b/src/view/com/pager/PagerWithHeader.tsx @@ -71,7 +71,8 @@ export const PagerWithHeader = React.forwardRef<PagerRef, PagerWithHeaderProps>( (evt: LayoutChangeEvent) => { const height = evt.nativeEvent.layout.height if (height > 0) { - setTabBarHeight(height) + // The rounding is necessary to prevent jumps on iOS + setTabBarHeight(Math.round(height)) } }, [setTabBarHeight], @@ -80,7 +81,8 @@ export const PagerWithHeader = React.forwardRef<PagerRef, PagerWithHeaderProps>( (evt: LayoutChangeEvent) => { const height = evt.nativeEvent.layout.height if (height > 0) { - setHeaderOnlyHeight(height) + // The rounding is necessary to prevent jumps on iOS + setHeaderOnlyHeight(Math.round(height)) } }, [setHeaderOnlyHeight], diff --git a/src/view/com/profile/ProfileHeader.tsx b/src/view/com/profile/ProfileHeader.tsx index 16e98ddf2..39e3e42ec 100644 --- a/src/view/com/profile/ProfileHeader.tsx +++ b/src/view/com/profile/ProfileHeader.tsx @@ -620,11 +620,17 @@ let ProfileHeaderLoaded = ({ <ProfileHeaderAlerts moderation={moderation} /> </View> - {!isProfilePreview && ( + {!isProfilePreview && showSuggestedFollows && ( <ProfileHeaderSuggestedFollows actorDid={profile.did} - active={showSuggestedFollows} - requestDismiss={() => setShowSuggestedFollows(!showSuggestedFollows)} + requestDismiss={() => { + if (showSuggestedFollows) { + setShowSuggestedFollows(false) + } else { + track('ProfileHeader:SuggestedFollowsOpened') + setShowSuggestedFollows(true) + } + }} /> )} diff --git a/src/view/com/profile/ProfileHeaderSuggestedFollows.tsx b/src/view/com/profile/ProfileHeaderSuggestedFollows.tsx index 1d550aa5c..ce5cf92c5 100644 --- a/src/view/com/profile/ProfileHeaderSuggestedFollows.tsx +++ b/src/view/com/profile/ProfileHeaderSuggestedFollows.tsx @@ -1,11 +1,5 @@ import React from 'react' import {View, StyleSheet, Pressable, ScrollView} from 'react-native' -import Animated, { - useSharedValue, - withTiming, - useAnimatedStyle, - Easing, -} from 'react-native-reanimated' import {AppBskyActorDefs, moderateProfile} from '@atproto/api' import { FontAwesomeIcon, @@ -34,112 +28,84 @@ const TOTAL_HEIGHT = 250 export function ProfileHeaderSuggestedFollows({ actorDid, - active, requestDismiss, }: { actorDid: string - active: boolean requestDismiss: () => void }) { - const {track} = useAnalytics() const pal = usePalette('default') - const animatedHeight = useSharedValue(0) - const animatedStyles = useAnimatedStyle(() => ({ - opacity: animatedHeight.value / TOTAL_HEIGHT, - height: animatedHeight.value, - })) - - React.useEffect(() => { - if (active) { - track('ProfileHeader:SuggestedFollowsOpened') - - animatedHeight.value = withTiming(TOTAL_HEIGHT, { - duration: 500, - easing: Easing.inOut(Easing.exp), - }) - } else { - animatedHeight.value = withTiming(0, { - duration: 500, - easing: Easing.inOut(Easing.exp), - }) - } - }, [active, animatedHeight, track]) - const {isLoading, data} = useSuggestedFollowsByActorQuery({ did: actorDid, }) - return ( - <Animated.View - pointerEvents="box-none" - style={[{overflow: 'hidden', opacity: 0}, animatedStyles]}> - <View style={{paddingVertical: OUTER_PADDING}} pointerEvents="box-none"> + <View + style={{paddingVertical: OUTER_PADDING, height: TOTAL_HEIGHT}} + pointerEvents="box-none"> + <View + pointerEvents="box-none" + style={{ + backgroundColor: pal.viewLight.backgroundColor, + height: '100%', + paddingTop: INNER_PADDING / 2, + }}> <View pointerEvents="box-none" style={{ - backgroundColor: pal.viewLight.backgroundColor, - height: '100%', - paddingTop: INNER_PADDING / 2, + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + paddingTop: 4, + paddingBottom: INNER_PADDING / 2, + paddingLeft: INNER_PADDING, + paddingRight: INNER_PADDING / 2, }}> - <View - pointerEvents="box-none" - style={{ - flexDirection: 'row', - justifyContent: 'space-between', - alignItems: 'center', - paddingTop: 4, - paddingBottom: INNER_PADDING / 2, - paddingLeft: INNER_PADDING, - paddingRight: INNER_PADDING / 2, - }}> - <Text type="sm-bold" style={[pal.textLight]}> - Suggested for you - </Text> - - <Pressable - accessibilityRole="button" - onPress={requestDismiss} - hitSlop={10} - style={{padding: INNER_PADDING / 2}}> - <FontAwesomeIcon - icon="x" - size={12} - style={pal.textLight as FontAwesomeIconStyle} - /> - </Pressable> - </View> + <Text type="sm-bold" style={[pal.textLight]}> + Suggested for you + </Text> - <ScrollView - horizontal={true} - showsHorizontalScrollIndicator={isWeb} - persistentScrollbar={true} - scrollIndicatorInsets={{bottom: 0}} - scrollEnabled={true} - contentContainerStyle={{ - alignItems: 'flex-start', - paddingLeft: INNER_PADDING / 2, - paddingBottom: INNER_PADDING, - }}> - {isLoading ? ( - <> - <SuggestedFollowSkeleton /> - <SuggestedFollowSkeleton /> - <SuggestedFollowSkeleton /> - <SuggestedFollowSkeleton /> - <SuggestedFollowSkeleton /> - <SuggestedFollowSkeleton /> - </> - ) : data ? ( - data.suggestions.map(profile => ( - <SuggestedFollow key={profile.did} profile={profile} /> - )) - ) : ( - <View /> - )} - </ScrollView> + <Pressable + accessibilityRole="button" + onPress={requestDismiss} + hitSlop={10} + style={{padding: INNER_PADDING / 2}}> + <FontAwesomeIcon + icon="x" + size={12} + style={pal.textLight as FontAwesomeIconStyle} + /> + </Pressable> </View> + + <ScrollView + horizontal={true} + showsHorizontalScrollIndicator={isWeb} + persistentScrollbar={true} + scrollIndicatorInsets={{bottom: 0}} + scrollEnabled={true} + contentContainerStyle={{ + alignItems: 'flex-start', + paddingLeft: INNER_PADDING / 2, + paddingBottom: INNER_PADDING, + }}> + {isLoading ? ( + <> + <SuggestedFollowSkeleton /> + <SuggestedFollowSkeleton /> + <SuggestedFollowSkeleton /> + <SuggestedFollowSkeleton /> + <SuggestedFollowSkeleton /> + <SuggestedFollowSkeleton /> + </> + ) : data ? ( + data.suggestions.map(profile => ( + <SuggestedFollow key={profile.did} profile={profile} /> + )) + ) : ( + <View /> + )} + </ScrollView> </View> - </Animated.View> + </View> ) } |