diff options
author | dan <dan.abramov@gmail.com> | 2025-01-10 00:32:08 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-01-10 00:32:08 +0000 |
commit | 02dbcc134ef9f9870c4f6eab2da93773b8310d67 (patch) | |
tree | c69ac4c1a43f350a2eb01dd78dfec20d00bb9224 /src | |
parent | 72dc508cb7f678df50ebb41db9adbcf826ed6975 (diff) | |
download | voidsky-02dbcc134ef9f9870c4f6eab2da93773b8310d67.tar.zst |
Fix trending swipe gesture (#7417)
Diffstat (limited to 'src')
-rw-r--r-- | src/components/interstitials/Trending.tsx | 164 | ||||
-rw-r--r-- | src/view/shell/TrendingGestureContext.tsx | 7 | ||||
-rw-r--r-- | src/view/shell/index.tsx | 13 |
3 files changed, 105 insertions, 79 deletions
diff --git a/src/components/interstitials/Trending.tsx b/src/components/interstitials/Trending.tsx index 9a5feb2b6..3e0308e43 100644 --- a/src/components/interstitials/Trending.tsx +++ b/src/components/interstitials/Trending.tsx @@ -1,6 +1,6 @@ -import React from 'react' -import {View} from 'react-native' -import {ScrollView} from 'react-native-gesture-handler' +import React, {useContext} from 'react' +import {ScrollView, View} from 'react-native' +import {GestureDetector} from 'react-native-gesture-handler' import {msg} from '@lingui/macro' import {useLingui} from '@lingui/react' @@ -12,6 +12,7 @@ import { import {useTrendingTopics} from '#/state/queries/trending/useTrendingTopics' import {useTrendingConfig} from '#/state/trending-config' import {LoadingPlaceholder} from '#/view/com/util/LoadingPlaceholder' +import {TrendingGestureContext} from '#/view/shell/TrendingGestureContext' import {atoms as a, useGutters, useTheme} from '#/alf' import {Button, ButtonIcon} from '#/components/Button' import {TimesLarge_Stroke2_Corner0_Rounded as X} from '#/components/icons/Times' @@ -40,83 +41,92 @@ export function Inner() { setTrendingDisabled(true) }, [setTrendingDisabled]) + // This is coordinated to take precedence over the drawer pan gesture. + const trendingScrollGesture = useContext(TrendingGestureContext) + return error || noTopics ? null : ( <View style={[t.atoms.border_contrast_low, a.border_t]}> - <ScrollView - horizontal - showsHorizontalScrollIndicator={false} - decelerationRate="fast"> - <View style={[gutters, a.flex_row, a.align_center, a.gap_lg]}> - <View style={{paddingLeft: 4, paddingRight: 2}}> - <Graph size="sm" /> - </View> - {isLoading ? ( - <View style={[a.py_lg, a.flex_row, a.gap_lg, a.align_center]}> - <LoadingPlaceholder - width={80} - height={undefined} - style={{alignSelf: 'stretch'}} - /> - <LoadingPlaceholder - width={50} - height={undefined} - style={{alignSelf: 'stretch'}} - /> - <LoadingPlaceholder - width={120} - height={undefined} - style={{alignSelf: 'stretch'}} - /> - <LoadingPlaceholder - width={30} - height={undefined} - style={{alignSelf: 'stretch'}} - /> - <LoadingPlaceholder - width={180} - height={undefined} - style={{alignSelf: 'stretch'}} - /> - <Text - style={[t.atoms.text_contrast_medium, a.text_sm, a.font_bold]}> - {' '} - </Text> + <GestureDetector gesture={trendingScrollGesture}> + <ScrollView + horizontal + showsHorizontalScrollIndicator={false} + decelerationRate="fast"> + <View style={[gutters, a.flex_row, a.align_center, a.gap_lg]}> + <View style={{paddingLeft: 4, paddingRight: 2}}> + <Graph size="sm" /> </View> - ) : !trending?.topics ? null : ( - <> - {trending.topics.map(topic => ( - <TrendingTopicLink - key={topic.link} - topic={topic} - onPress={() => { - logEvent('trendingTopic:click', {context: 'interstitial'}) - }}> - <View style={[a.py_lg]}> - <Text - style={[ - t.atoms.text, - a.text_sm, - a.font_bold, - {opacity: 0.7}, // NOTE: we use opacity 0.7 instead of a color to match the color of the home pager tab bar - ]}> - {topic.topic} - </Text> - </View> - </TrendingTopicLink> - ))} - <Button - label={_(msg`Hide trending topics`)} - size="tiny" - variant="ghost" - color="secondary" - shape="round" - onPress={() => trendingPrompt.open()}> - <ButtonIcon icon={X} /> - </Button> - </> - )} - </View> - </ScrollView> + {isLoading ? ( + <View style={[a.py_lg, a.flex_row, a.gap_lg, a.align_center]}> + <LoadingPlaceholder + width={80} + height={undefined} + style={{alignSelf: 'stretch'}} + /> + <LoadingPlaceholder + width={50} + height={undefined} + style={{alignSelf: 'stretch'}} + /> + <LoadingPlaceholder + width={120} + height={undefined} + style={{alignSelf: 'stretch'}} + /> + <LoadingPlaceholder + width={30} + height={undefined} + style={{alignSelf: 'stretch'}} + /> + <LoadingPlaceholder + width={180} + height={undefined} + style={{alignSelf: 'stretch'}} + /> + <Text + style={[ + t.atoms.text_contrast_medium, + a.text_sm, + a.font_bold, + ]}> + {' '} + </Text> + </View> + ) : !trending?.topics ? null : ( + <> + {trending.topics.map(topic => ( + <TrendingTopicLink + key={topic.link} + topic={topic} + onPress={() => { + logEvent('trendingTopic:click', {context: 'interstitial'}) + }}> + <View style={[a.py_lg]}> + <Text + style={[ + t.atoms.text, + a.text_sm, + a.font_bold, + {opacity: 0.7}, // NOTE: we use opacity 0.7 instead of a color to match the color of the home pager tab bar + ]}> + {topic.topic} + </Text> + </View> + </TrendingTopicLink> + ))} + <Button + label={_(msg`Hide trending topics`)} + size="tiny" + variant="ghost" + color="secondary" + shape="round" + onPress={() => trendingPrompt.open()}> + <ButtonIcon icon={X} /> + </Button> + </> + )} + </View> + </ScrollView> + </GestureDetector> <Prompt.Basic control={trendingPrompt} diff --git a/src/view/shell/TrendingGestureContext.tsx b/src/view/shell/TrendingGestureContext.tsx new file mode 100644 index 000000000..8f21f444b --- /dev/null +++ b/src/view/shell/TrendingGestureContext.tsx @@ -0,0 +1,7 @@ +import {createContext} from 'react' +import {Gesture} from 'react-native-gesture-handler' + +// Not really used but serves as a fallback for types. +const noopGesture = Gesture.Native() + +export const TrendingGestureContext = createContext(noopGesture) diff --git a/src/view/shell/index.tsx b/src/view/shell/index.tsx index a5e97610d..80e63c6bc 100644 --- a/src/view/shell/index.tsx +++ b/src/view/shell/index.tsx @@ -1,6 +1,7 @@ -import {useCallback, useEffect} from 'react' +import {useCallback, useEffect, useState} from 'react' import {BackHandler, useWindowDimensions, View} from 'react-native' import {Drawer} from 'react-native-drawer-layout' +import {Gesture} from 'react-native-gesture-handler' import {useSafeAreaInsets} from 'react-native-safe-area-context' import {StatusBar} from 'expo-status-bar' import {useNavigation, useNavigationState} from '@react-navigation/native' @@ -33,6 +34,7 @@ import {BottomSheetOutlet} from '../../../modules/bottom-sheet' import {updateActiveViewAsync} from '../../../modules/expo-bluesky-swiss-army/src/VisibilityView' import {Composer} from './Composer' import {DrawerContent} from './Drawer' +import {TrendingGestureContext} from './TrendingGestureContext' function ShellInner() { const t = useTheme() @@ -92,6 +94,7 @@ function ShellInner() { }, [dedupe, navigation]) const swipeEnabled = !canGoBack && hasSession && !isDrawerSwipeDisabled + const [trendingScrollGesture] = useState(() => Gesture.Native()) return ( <> <View style={[a.h_full]}> @@ -101,6 +104,10 @@ function ShellInner() { renderDrawerContent={renderDrawerContent} drawerStyle={{width: Math.min(400, winDim.width * 0.8)}} configureGestureHandler={handler => { + handler = handler.requireExternalGestureToFail( + trendingScrollGesture, + ) + if (swipeEnabled) { if (isDrawerOpen) { return handler.activeOffsetX([-1, 1]) @@ -138,7 +145,9 @@ function ShellInner() { dim: 'rgba(10, 13, 16, 0.8)', }), }}> - <TabsNavigator /> + <TrendingGestureContext.Provider value={trendingScrollGesture}> + <TabsNavigator /> + </TrendingGestureContext.Provider> </Drawer> </ErrorBoundary> </View> |