From 8d5a744bb3075f140b731ec77e22e39bb3482fcc Mon Sep 17 00:00:00 2001 From: Ovidiu Cristescu <55203625+LunatiqueCoder@users.noreply.github.com> Date: Sun, 11 Aug 2024 00:14:52 +0300 Subject: [PATCH] 1104-flatlist-gesture-handling-enhancement --- packages/media-console/src/VideoPlayer.tsx | 5 ++-- .../src/hooks/usePanResponders.tsx | 23 ++++++++++----- packages/media-console/src/types.ts | 29 +++++++++++++++++-- 3 files changed, 43 insertions(+), 14 deletions(-) diff --git a/packages/media-console/src/VideoPlayer.tsx b/packages/media-console/src/VideoPlayer.tsx index 9ee82de..14575c5 100644 --- a/packages/media-console/src/VideoPlayer.tsx +++ b/packages/media-console/src/VideoPlayer.tsx @@ -74,7 +74,7 @@ const AnimatedVideoPlayer = ( disableOverlay, navigator, rewindTime = 15, - pan: {horizontal: horizontalPan, inverted: invertedPan} = {}, + pan, testID, } = props; @@ -291,8 +291,7 @@ const AnimatedVideoPlayer = ( setSeeking, setControlTimeout, onEnd: events.onEnd, - horizontal: horizontalPan, - inverted: invertedPan, + pan, }); useEffect(() => { diff --git a/packages/media-console/src/hooks/usePanResponders.tsx b/packages/media-console/src/hooks/usePanResponders.tsx index e9618d3..8c3ad93 100644 --- a/packages/media-console/src/hooks/usePanResponders.tsx +++ b/packages/media-console/src/hooks/usePanResponders.tsx @@ -1,7 +1,8 @@ import {Dispatch, SetStateAction, useEffect} from 'react'; import {PanResponder} from 'react-native'; +import {VideoPlayerProps} from '../types'; -interface PanRespondersProps { +interface PanRespondersProps extends Pick { duration: number; seekerOffset: number; volumeOffset: number; @@ -16,8 +17,6 @@ interface PanRespondersProps { setSeeking: Dispatch>; setControlTimeout: () => void; onEnd: () => void; - horizontal?: boolean; - inverted?: boolean; } export const usePanResponders = ({ @@ -35,14 +34,19 @@ export const usePanResponders = ({ setSeeking, setControlTimeout, onEnd, - horizontal = true, - inverted = false, + pan: {horizontal = true, inverted = false, parentList} = {}, }: PanRespondersProps) => { + const enableParentScroll = () => + parentList?.ref?.current?.setNativeProps({ + scrollEnabled: parentList?.scrollEnabled, + }); + const volumePanResponder = PanResponder.create({ onStartShouldSetPanResponder: () => true, onMoveShouldSetPanResponder: () => true, onPanResponderGrant: () => { clearControlTimeout(); + parentList?.ref?.current?.setNativeProps({scrollEnabled: false}); }, onPanResponderMove: (_evt, gestureState) => { const diff = horizontal ? gestureState.dx : gestureState.dy; @@ -52,6 +56,8 @@ export const usePanResponders = ({ onPanResponderRelease: () => { setControlTimeout(); }, + onPanResponderEnd: enableParentScroll, + onPanResponderTerminationRequest: () => false, // https://stackoverflow.com/a/76875305/14056591 }); const seekPanResponder = PanResponder.create({ @@ -62,6 +68,7 @@ export const usePanResponders = ({ clearControlTimeout(); const position = evt.nativeEvent.locationX; setSeekerPosition(position); + parentList?.ref?.current?.setNativeProps({scrollEnabled: false}); }, onPanResponderMove: (_evt, gestureState) => { const diff = horizontal ? gestureState.dx : gestureState.dy; @@ -74,14 +81,14 @@ export const usePanResponders = ({ const time = duration * percent; if (time >= duration && !loading) { - if (typeof onEnd === 'function') { - onEnd(); - } + onEnd?.(); } setSeeking(false); seek && seek(time); }, + onPanResponderEnd: enableParentScroll, + onPanResponderTerminationRequest: () => false, // https://stackoverflow.com/a/76875305/14056591 }); useEffect(() => { diff --git a/packages/media-console/src/types.ts b/packages/media-console/src/types.ts index 87c401b..00a6214 100644 --- a/packages/media-console/src/types.ts +++ b/packages/media-console/src/types.ts @@ -1,5 +1,11 @@ import type {RefObject} from 'react'; -import type {ViewStyle, StyleProp, Animated} from 'react-native'; +import { + ViewStyle, + StyleProp, + Animated, + FlatList, + ScrollView, +} from 'react-native'; import type Reanimated from 'react-native-reanimated'; import type {StyleProps} from 'react-native-reanimated'; import type {VideoRef, ReactVideoProps} from 'react-native-video'; @@ -245,7 +251,7 @@ export interface VideoPlayerProps extends ReactVideoProps { rewindTime?: number; /** - * Object allowing fine grained control of the pan responder + * Object allowing fine-grained control of the pan responder * * @default { horizontal: true, inverted: false } */ @@ -256,13 +262,30 @@ export interface VideoPlayerProps extends ReactVideoProps { * @default true */ horizontal?: boolean; - /** * Boolean representing if the player controls pan gesture should be inverted * * @default false */ inverted?: boolean; + /** + * Options to make the video player work seamlessly within FlatLists or ScrollViews. + * + * @link https://github.com/LunatiqueCoder/react-native-media-console/issues/104 + */ + parentList?: { + /** + * Internally, `ref?.current?.setNativeProps({scrollEnabled: boolean});` is used in order + * to fix this issue: + * @link https://github.com/LunatiqueCoder/react-native-media-console/issues/104 + */ + ref: RefObject; + /** + * Used to keep a consistency when using `ref?.current?.setNativeProps({scrollEnabled: boolean});`. + * @see ref + */ + scrollEnabled: boolean; + }; }; /** * testID selector for testing