import React, { useCallback, useEffect, useRef } from "react";
import { StyleSheet } from "react-native";
import { Gesture, GestureDetector } from "react-native-gesture-handler";
import Animated, {
useAnimatedScrollHandler,
useAnimatedStyle,
useSharedValue,
withTiming,
runOnJS,
scrollTo,
} from "react-native-reanimated";
import { useHeaderTabContext } from "./context";
import { useSharedScrollableRef, useSyncInitialPosition } from "./hooks";
import type { SceneProps } from "./types";
import { SCROLLABLE_STATE } from "./constants";
export function SceneComponent
({
index,
onScroll: propOnScroll,
onContentSizeChange,
ContainerView,
contentContainerStyle,
scrollIndicatorInsets,
forwardedRef,
useExternalScrollView = false,
...restProps
}: SceneProps
) {
//#region refs
const nativeGestureRef = useRef(Gesture.Native());
const scollViewRef =
useSharedScrollableRef(forwardedRef);
//#endregion
//#region hooks
const {
shareAnimatedValue,
headerHeight,
expectHeight,
refHasChanged,
updateSceneInfo,
scrollViewPaddingTop,
animatedScrollableState,
disableBounces,
} = useHeaderTabContext();
//#endregion
//#region animations/style
const scrollY = useSharedValue(0);
const { opacityValue, initialPosition } =
useSyncInitialPosition(scollViewRef);
const sceneStyle = useAnimatedStyle(() => {
return {
opacity: withTiming(opacityValue.value),
};
}, [opacityValue]);
//#endregion
//#region methods
const onScrollAnimateEvent = useAnimatedScrollHandler({
onScroll: (e) => {
scrollY.value = e.contentOffset.y;
if (animatedScrollableState.value === SCROLLABLE_STATE.LOCKED) {
scrollTo(scollViewRef, 0, 0, false);
} else {
shareAnimatedValue.value = e.contentOffset.y;
}
if (propOnScroll) {
runOnJS(propOnScroll as any)({ nativeEvent: e });
}
},
onBeginDrag: () => {
if (disableBounces) {
disableBounces.value = true;
}
// console.log("onBeginDrag");
},
// onEndDrag: (e) => {
// console.log("onEndDrag");
// },
// onMomentumEnd: () => {
// console.log("onMomentumEnd");
// },
// onMomentumBegin: () => {
// console.log("onMomentumBegin");
// },
});
// adjust the scene size
const _onContentSizeChange = useCallback(
(contentWidth: number, contentHeight: number) => {
onContentSizeChange?.(contentWidth, contentHeight);
if (Math.ceil(contentHeight) >= expectHeight) {
initialPosition(shareAnimatedValue.value);
}
},
[onContentSizeChange, initialPosition, expectHeight, shareAnimatedValue]
);
//#endregion
useEffect(() => {
refHasChanged?.(nativeGestureRef.current);
}, [refHasChanged]);
useEffect(() => {
if (scollViewRef && scollViewRef.current) {
updateSceneInfo({
scrollRef: scollViewRef,
index,
scrollY,
});
}
}, [scollViewRef, index, scrollY, updateSceneInfo]);
return (
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
});