An ATproto social media client -- with an independent Appview.

Remove vertical scrollbars from views on native (#3429)

* remove vertical scrollbars

* add to a few missing lists

* gate this change

* use `hide_vertical_scroll_indicators`

* fix gate lint

* fix bool

authored by hailey.at and committed by

GitHub c3821fdc 6218eb0e

+87 -50
+1
src/lib/statsig/gates.ts
··· 3 3 | 'autoexpand_suggestions_on_profile_follow' 4 4 | 'disable_min_shell_on_foregrounding' 5 5 | 'disable_poll_on_discover' 6 + | 'hide_vertical_scroll_indicators' 6 7 | 'new_profile_scroll_component' 7 8 | 'new_search' 8 9 | 'receive_updates'
+11 -9
src/view/com/auth/onboarding/RecommendedFeeds.tsx
··· 1 1 import React from 'react' 2 2 import {ActivityIndicator, FlatList, StyleSheet, View} from 'react-native' 3 3 import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' 4 - import {TabletOrDesktop, Mobile} from 'view/com/util/layouts/Breakpoints' 4 + import {msg, Trans} from '@lingui/macro' 5 + import {useLingui} from '@lingui/react' 6 + 7 + import {useSuggestedFeedsQuery} from '#/state/queries/suggested-feeds' 8 + import {usePalette} from 'lib/hooks/usePalette' 9 + import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' 10 + import {ErrorMessage} from 'view/com/util/error/ErrorMessage' 11 + import {Button} from 'view/com/util/forms/Button' 12 + import {Mobile, TabletOrDesktop} from 'view/com/util/layouts/Breakpoints' 13 + import {TitleColumnLayout} from 'view/com/util/layouts/TitleColumnLayout' 5 14 import {Text} from 'view/com/util/text/Text' 6 15 import {ViewHeader} from 'view/com/util/ViewHeader' 7 - import {TitleColumnLayout} from 'view/com/util/layouts/TitleColumnLayout' 8 - import {Button} from 'view/com/util/forms/Button' 9 16 import {RecommendedFeedsItem} from './RecommendedFeedsItem' 10 - import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' 11 - import {usePalette} from 'lib/hooks/usePalette' 12 - import {ErrorMessage} from 'view/com/util/error/ErrorMessage' 13 - import {Trans, msg} from '@lingui/macro' 14 - import {useLingui} from '@lingui/react' 15 - import {useSuggestedFeedsQuery} from '#/state/queries/suggested-feeds' 16 17 17 18 type Props = { 18 19 next: () => void ··· 130 131 renderItem={({item}) => <RecommendedFeedsItem item={item} />} 131 132 keyExtractor={item => item.uri} 132 133 style={{flex: 1}} 134 + showsVerticalScrollIndicator={false} 133 135 /> 134 136 ) : isLoading ? ( 135 137 <View style={{flex: 1}}>
+14 -12
src/view/com/auth/onboarding/RecommendedFollows.tsx
··· 1 1 import React from 'react' 2 2 import {ActivityIndicator, FlatList, StyleSheet, View} from 'react-native' 3 + import {AppBskyActorDefs, moderateProfile} from '@atproto/api' 3 4 import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' 4 - import {AppBskyActorDefs, moderateProfile} from '@atproto/api' 5 - import {TabletOrDesktop, Mobile} from 'view/com/util/layouts/Breakpoints' 5 + import {msg, Trans} from '@lingui/macro' 6 + import {useLingui} from '@lingui/react' 7 + 8 + import {logger} from '#/logger' 9 + import {useModerationOpts} from '#/state/queries/preferences' 10 + import {useSuggestedFollowsQuery} from '#/state/queries/suggested-follows' 11 + import {useGetSuggestedFollowersByActor} from '#/state/queries/suggested-follows' 12 + import {usePalette} from 'lib/hooks/usePalette' 13 + import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' 14 + import {Button} from 'view/com/util/forms/Button' 15 + import {Mobile, TabletOrDesktop} from 'view/com/util/layouts/Breakpoints' 16 + import {TitleColumnLayout} from 'view/com/util/layouts/TitleColumnLayout' 6 17 import {Text} from 'view/com/util/text/Text' 7 18 import {ViewHeader} from 'view/com/util/ViewHeader' 8 - import {TitleColumnLayout} from 'view/com/util/layouts/TitleColumnLayout' 9 - import {Button} from 'view/com/util/forms/Button' 10 - import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' 11 - import {usePalette} from 'lib/hooks/usePalette' 12 19 import {RecommendedFollowsItem} from './RecommendedFollowsItem' 13 - import {useSuggestedFollowsQuery} from '#/state/queries/suggested-follows' 14 - import {useGetSuggestedFollowersByActor} from '#/state/queries/suggested-follows' 15 - import {useModerationOpts} from '#/state/queries/preferences' 16 - import {logger} from '#/logger' 17 - import {Trans, msg} from '@lingui/macro' 18 - import {useLingui} from '@lingui/react' 19 20 20 21 type Props = { 21 22 next: () => void ··· 202 203 )} 203 204 keyExtractor={item => item.did} 204 205 style={{flex: 1}} 206 + showsVerticalScrollIndicator={false} 205 207 /> 206 208 )} 207 209 <Button
+9 -4
src/view/com/util/List.tsx
··· 1 1 import React, {memo} from 'react' 2 2 import {FlatListProps, RefreshControl} from 'react-native' 3 - import {FlatList_INTERNAL} from './Views' 4 - import {addStyle} from 'lib/styles' 5 - import {useScrollHandlers} from '#/lib/ScrollContext' 6 3 import {runOnJS, useSharedValue} from 'react-native-reanimated' 4 + 7 5 import {useAnimatedScrollHandler} from '#/lib/hooks/useAnimatedScrollHandler_FIXED' 8 6 import {usePalette} from '#/lib/hooks/usePalette' 7 + import {useScrollHandlers} from '#/lib/ScrollContext' 8 + import {useGate} from 'lib/statsig/statsig' 9 + import {addStyle} from 'lib/styles' 10 + import {isWeb} from 'platform/detection' 11 + import {FlatList_INTERNAL} from './Views' 9 12 10 13 export type ListMethods = FlatList_INTERNAL 11 14 export type ListProps<ItemT> = Omit< ··· 37 40 const isScrolledDown = useSharedValue(false) 38 41 const contextScrollHandlers = useScrollHandlers() 39 42 const pal = usePalette('default') 40 - 43 + const showsVerticalScrollIndicator = 44 + !useGate('hide_vertical_scroll_indicators') || isWeb 41 45 function handleScrolledDownChange(didScrollDown: boolean) { 42 46 onScrolledDownChange?.(didScrollDown) 43 47 } ··· 93 97 scrollEventThrottle={1} 94 98 style={style} 95 99 ref={ref} 100 + showsVerticalScrollIndicator={showsVerticalScrollIndicator} 96 101 /> 97 102 ) 98 103 }
+15 -1
src/view/com/util/Views.jsx
··· 2 2 import {View} from 'react-native' 3 3 import Animated from 'react-native-reanimated' 4 4 5 + import {useGate} from 'lib/statsig/statsig' 6 + 5 7 export const FlatList_INTERNAL = Animated.FlatList 6 - export const ScrollView = Animated.ScrollView 7 8 export function CenteredView(props) { 8 9 return <View {...props} /> 9 10 } 11 + 12 + export function ScrollView(props) { 13 + const showsVerticalScrollIndicator = !useGate( 14 + 'hide_vertical_scroll_indicators', 15 + ) 16 + 17 + return ( 18 + <Animated.ScrollView 19 + {...props} 20 + showsVerticalScrollIndicator={showsVerticalScrollIndicator} 21 + /> 22 + ) 23 + }
+19 -12
src/view/screens/ModerationBlockedAccounts.tsx
··· 7 7 View, 8 8 } from 'react-native' 9 9 import {AppBskyActorDefs as ActorDefs} from '@atproto/api' 10 - import {Text} from '../com/util/text/Text' 10 + import {msg, Trans} from '@lingui/macro' 11 + import {useLingui} from '@lingui/react' 12 + import {useFocusEffect} from '@react-navigation/native' 13 + import {NativeStackScreenProps} from '@react-navigation/native-stack' 14 + 15 + import {cleanError} from '#/lib/strings/errors' 16 + import {logger} from '#/logger' 17 + import {useMyBlockedAccountsQuery} from '#/state/queries/my-blocked-accounts' 18 + import {useSetMinimalShellMode} from '#/state/shell' 19 + import {useAnalytics} from 'lib/analytics/analytics' 11 20 import {usePalette} from 'lib/hooks/usePalette' 12 21 import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' 13 - import {NativeStackScreenProps} from '@react-navigation/native-stack' 14 22 import {CommonNavigatorParams} from 'lib/routes/types' 15 - import {useAnalytics} from 'lib/analytics/analytics' 16 - import {useFocusEffect} from '@react-navigation/native' 17 - import {ViewHeader} from '../com/util/ViewHeader' 23 + import {useGate} from 'lib/statsig/statsig' 24 + import {isWeb} from 'platform/detection' 25 + import {ProfileCard} from 'view/com/profile/ProfileCard' 18 26 import {CenteredView} from 'view/com/util/Views' 19 27 import {ErrorScreen} from '../com/util/error/ErrorScreen' 20 - import {ProfileCard} from 'view/com/profile/ProfileCard' 21 - import {logger} from '#/logger' 22 - import {useSetMinimalShellMode} from '#/state/shell' 23 - import {Trans, msg} from '@lingui/macro' 24 - import {useLingui} from '@lingui/react' 25 - import {useMyBlockedAccountsQuery} from '#/state/queries/my-blocked-accounts' 26 - import {cleanError} from '#/lib/strings/errors' 28 + import {Text} from '../com/util/text/Text' 29 + import {ViewHeader} from '../com/util/ViewHeader' 27 30 28 31 type Props = NativeStackScreenProps< 29 32 CommonNavigatorParams, ··· 35 38 const setMinimalShellMode = useSetMinimalShellMode() 36 39 const {isTabletOrDesktop} = useWebMediaQueries() 37 40 const {screen} = useAnalytics() 41 + const showsVerticalScrollIndicator = 42 + !useGate('hide_vertical_scroll_indicators') || isWeb 43 + 38 44 const [isPTRing, setIsPTRing] = React.useState(false) 39 45 const { 40 46 data, ··· 163 169 )} 164 170 // @ts-ignore our .web version only -prf 165 171 desktopFixedHeight 172 + showsVerticalScrollIndicator={showsVerticalScrollIndicator} 166 173 /> 167 174 )} 168 175 </CenteredView>
+18 -12
src/view/screens/ModerationMutedAccounts.tsx
··· 7 7 View, 8 8 } from 'react-native' 9 9 import {AppBskyActorDefs as ActorDefs} from '@atproto/api' 10 - import {Text} from '../com/util/text/Text' 10 + import {msg, Trans} from '@lingui/macro' 11 + import {useLingui} from '@lingui/react' 12 + import {useFocusEffect} from '@react-navigation/native' 13 + import {NativeStackScreenProps} from '@react-navigation/native-stack' 14 + 15 + import {cleanError} from '#/lib/strings/errors' 16 + import {logger} from '#/logger' 17 + import {useMyMutedAccountsQuery} from '#/state/queries/my-muted-accounts' 18 + import {useSetMinimalShellMode} from '#/state/shell' 19 + import {useAnalytics} from 'lib/analytics/analytics' 11 20 import {usePalette} from 'lib/hooks/usePalette' 12 21 import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' 13 - import {NativeStackScreenProps} from '@react-navigation/native-stack' 14 22 import {CommonNavigatorParams} from 'lib/routes/types' 15 - import {useAnalytics} from 'lib/analytics/analytics' 16 - import {useFocusEffect} from '@react-navigation/native' 17 - import {ViewHeader} from '../com/util/ViewHeader' 23 + import {useGate} from 'lib/statsig/statsig' 24 + import {isWeb} from 'platform/detection' 25 + import {ProfileCard} from 'view/com/profile/ProfileCard' 18 26 import {CenteredView} from 'view/com/util/Views' 19 27 import {ErrorScreen} from '../com/util/error/ErrorScreen' 20 - import {ProfileCard} from 'view/com/profile/ProfileCard' 21 - import {logger} from '#/logger' 22 - import {useSetMinimalShellMode} from '#/state/shell' 23 - import {Trans, msg} from '@lingui/macro' 24 - import {useLingui} from '@lingui/react' 25 - import {useMyMutedAccountsQuery} from '#/state/queries/my-muted-accounts' 26 - import {cleanError} from '#/lib/strings/errors' 28 + import {Text} from '../com/util/text/Text' 29 + import {ViewHeader} from '../com/util/ViewHeader' 27 30 28 31 type Props = NativeStackScreenProps< 29 32 CommonNavigatorParams, ··· 35 38 const setMinimalShellMode = useSetMinimalShellMode() 36 39 const {isTabletOrDesktop} = useWebMediaQueries() 37 40 const {screen} = useAnalytics() 41 + const showsVerticalScrollIndicator = 42 + !useGate('hide_vertical_scroll_indicators') || isWeb 38 43 const [isPTRing, setIsPTRing] = React.useState(false) 39 44 const { 40 45 data, ··· 162 167 )} 163 168 // @ts-ignore our .web version only -prf 164 169 desktopFixedHeight 170 + showsVerticalScrollIndicator={showsVerticalScrollIndicator} 165 171 /> 166 172 )} 167 173 </CenteredView>