Simultaneous gesture
This commit is contained in:
@@ -7,7 +7,11 @@ import {
|
|||||||
View,
|
View,
|
||||||
ViewToken,
|
ViewToken,
|
||||||
} from 'react-native'
|
} from 'react-native'
|
||||||
import {Gesture, GestureDetector} from 'react-native-gesture-handler'
|
import {
|
||||||
|
Gesture,
|
||||||
|
GestureDetector,
|
||||||
|
NativeGesture,
|
||||||
|
} from 'react-native-gesture-handler'
|
||||||
import Animated, {
|
import Animated, {
|
||||||
runOnJS,
|
runOnJS,
|
||||||
runOnUI,
|
runOnUI,
|
||||||
@@ -157,6 +161,8 @@ function Inner() {
|
|||||||
|
|
||||||
const [currentIndex, setCurrentIndex] = useState(0)
|
const [currentIndex, setCurrentIndex] = useState(0)
|
||||||
|
|
||||||
|
const scrollGesture = useMemo(() => Gesture.Native(), [])
|
||||||
|
|
||||||
const renderItem: ListRenderItem<FeedPostSliceItem> = useCallback(
|
const renderItem: ListRenderItem<FeedPostSliceItem> = useCallback(
|
||||||
({item, index}) => {
|
({item, index}) => {
|
||||||
const {post} = item
|
const {post} = item
|
||||||
@@ -177,10 +183,11 @@ function Inner() {
|
|||||||
index === currentIndex &&
|
index === currentIndex &&
|
||||||
currentSource === post.embed.playlist
|
currentSource === post.embed.playlist
|
||||||
}
|
}
|
||||||
|
scrollGesture={scrollGesture}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
[players, currentIndex, isFocused, currentSources],
|
[players, currentIndex, isFocused, currentSources, scrollGesture],
|
||||||
)
|
)
|
||||||
|
|
||||||
const updateVideoState = useNonReactiveCallback((index?: number) => {
|
const updateVideoState = useNonReactiveCallback((index?: number) => {
|
||||||
@@ -307,29 +314,31 @@ function Inner() {
|
|||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<List
|
<GestureDetector gesture={scrollGesture}>
|
||||||
data={videos}
|
<List
|
||||||
renderItem={renderItem}
|
data={videos}
|
||||||
keyExtractor={keyExtractor}
|
renderItem={renderItem}
|
||||||
pagingEnabled={true}
|
keyExtractor={keyExtractor}
|
||||||
refreshing={isFetching}
|
pagingEnabled={true}
|
||||||
onRefresh={refetch}
|
refreshing={isFetching}
|
||||||
ListFooterComponent={
|
onRefresh={refetch}
|
||||||
<ListFooter
|
ListFooterComponent={
|
||||||
hasNextPage={hasNextPage}
|
<ListFooter
|
||||||
isFetchingNextPage={isFetchingNextPage}
|
hasNextPage={hasNextPage}
|
||||||
onRetry={refetch}
|
isFetchingNextPage={isFetchingNextPage}
|
||||||
/>
|
onRetry={refetch}
|
||||||
}
|
/>
|
||||||
onEndReached={() => {
|
|
||||||
if (hasNextPage && !isFetchingNextPage) {
|
|
||||||
fetchNextPage()
|
|
||||||
}
|
}
|
||||||
}}
|
onEndReached={() => {
|
||||||
showsVerticalScrollIndicator={false}
|
if (hasNextPage && !isFetchingNextPage) {
|
||||||
onViewableItemsChanged={onViewableItemsChanged}
|
fetchNextPage()
|
||||||
viewabilityConfig={{itemVisiblePercentThreshold: 95}}
|
}
|
||||||
/>
|
}}
|
||||||
|
showsVerticalScrollIndicator={false}
|
||||||
|
onViewableItemsChanged={onViewableItemsChanged}
|
||||||
|
viewabilityConfig={{itemVisiblePercentThreshold: 95}}
|
||||||
|
/>
|
||||||
|
</GestureDetector>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -342,11 +351,13 @@ function VideoItem({
|
|||||||
post,
|
post,
|
||||||
embed,
|
embed,
|
||||||
active,
|
active,
|
||||||
|
scrollGesture,
|
||||||
}: {
|
}: {
|
||||||
player?: VideoPlayer
|
player?: VideoPlayer
|
||||||
post: AppBskyFeedDefs.PostView
|
post: AppBskyFeedDefs.PostView
|
||||||
embed: AppBskyEmbedVideo.View
|
embed: AppBskyEmbedVideo.View
|
||||||
active: boolean
|
active: boolean
|
||||||
|
scrollGesture: NativeGesture
|
||||||
}) {
|
}) {
|
||||||
const postShadow = usePostShadow(post)
|
const postShadow = usePostShadow(post)
|
||||||
const {height, width} = useWindowDimensions()
|
const {height, width} = useWindowDimensions()
|
||||||
@@ -382,7 +393,12 @@ function VideoItem({
|
|||||||
)}
|
)}
|
||||||
{postShadow !== POST_TOMBSTONE ? (
|
{postShadow !== POST_TOMBSTONE ? (
|
||||||
player && (
|
player && (
|
||||||
<Overlay player={player} post={postShadow} active={active} />
|
<Overlay
|
||||||
|
player={player}
|
||||||
|
post={postShadow}
|
||||||
|
active={active}
|
||||||
|
scrollGesture={scrollGesture}
|
||||||
|
/>
|
||||||
)
|
)
|
||||||
) : (
|
) : (
|
||||||
<View
|
<View
|
||||||
@@ -466,10 +482,12 @@ function Overlay({
|
|||||||
player,
|
player,
|
||||||
post,
|
post,
|
||||||
active,
|
active,
|
||||||
|
scrollGesture,
|
||||||
}: {
|
}: {
|
||||||
player: VideoPlayer
|
player: VideoPlayer
|
||||||
post: Shadow<AppBskyFeedDefs.PostView>
|
post: Shadow<AppBskyFeedDefs.PostView>
|
||||||
active: boolean
|
active: boolean
|
||||||
|
scrollGesture: NativeGesture
|
||||||
}) {
|
}) {
|
||||||
const insets = useSafeAreaInsets()
|
const insets = useSafeAreaInsets()
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
@@ -504,19 +522,20 @@ function Overlay({
|
|||||||
|
|
||||||
const gesture = useMemo(() => {
|
const gesture = useMemo(() => {
|
||||||
const dragLeftGesture = Gesture.Pan()
|
const dragLeftGesture = Gesture.Pan()
|
||||||
|
.simultaneousWithExternalGesture(scrollGesture)
|
||||||
.activeOffsetX([0, 10])
|
.activeOffsetX([0, 10])
|
||||||
.failOffsetX([-10, 0])
|
.failOffsetX([-10, 0])
|
||||||
.failOffsetY([-5, 5])
|
.failOffsetY([-5, 5])
|
||||||
.maxPointers(1)
|
.maxPointers(1)
|
||||||
.onEnd(evt => {
|
.onEnd(evt => {
|
||||||
'worklet'
|
'worklet'
|
||||||
if (evt.translationX < -50) {
|
if (evt.translationX < -50 && evt.velocityX < -300) {
|
||||||
runOnJS(pushToProfile)()
|
runOnJS(pushToProfile)()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
return dragLeftGesture
|
return dragLeftGesture
|
||||||
}, [pushToProfile])
|
}, [pushToProfile, scrollGesture])
|
||||||
|
|
||||||
const rkey = new AtUri(post.uri).rkey
|
const rkey = new AtUri(post.uri).rkey
|
||||||
const record = AppBskyFeedPost.isRecord(post.record) ? post.record : undefined
|
const record = AppBskyFeedPost.isRecord(post.record) ? post.record : undefined
|
||||||
|
|||||||
Reference in New Issue
Block a user