import React, { memo } from "react"; import { ActivityIndicator, StyleSheet } from "react-native"; import Animated, { useAnimatedReaction, useAnimatedStyle, useDerivedValue, useSharedValue, SharedValue, } from "react-native-reanimated"; import { useRefreshDerivedValue } from "./hooks"; import { RefreshControlProps, RefreshTypeEnum } from "./types"; type RefreshControlContainerProps = { top: number; refreshHeight: number; overflowPull: number; opacityValue: SharedValue; refreshValue: SharedValue; isRefreshing: SharedValue; isRefreshingWithAnimation: SharedValue; pullExtendedCoefficient: number; renderContent?: (refreshProps: RefreshControlProps) => React.ReactElement; refreshControlColor?: string; }; const RefreshControlContainer: React.FC = ({ top, refreshHeight, overflowPull, opacityValue, refreshValue, isRefreshing, isRefreshingWithAnimation, pullExtendedCoefficient, renderContent, refreshControlColor = "#999999", }) => { const refreshType = useSharedValue(RefreshTypeEnum.Idle); const progress = useDerivedValue(() => { if (isRefreshingWithAnimation.value) return 1; return Math.min(refreshValue.value / refreshHeight, 1); }); const tranYValue = useSharedValue(0); useRefreshDerivedValue(tranYValue, { animatedValue: refreshValue, refreshHeight, overflowPull, pullExtendedCoefficient, }); useAnimatedReaction( () => { return { _progress: progress.value, _isRefreshing: isRefreshing.value, _isRefreshingWithAnimation: isRefreshingWithAnimation.value, }; }, ({ _progress, _isRefreshing, _isRefreshingWithAnimation }) => { if (_isRefreshing !== _isRefreshingWithAnimation) { refreshType.value = _isRefreshing ? RefreshTypeEnum.Pending : RefreshTypeEnum.Finish; return; } if (_isRefreshing) { refreshType.value = RefreshTypeEnum.Refreshing; } else { refreshType.value = _progress < 1 ? RefreshTypeEnum.Cancel : RefreshTypeEnum.Success; } }, [refreshHeight] ); const animatedStyle = useAnimatedStyle(() => { return { opacity: opacityValue.value, transform: [ { translateY: tranYValue.value, }, ], }; }); const _renderContent = () => { const _props = makeChildProps(); if (renderContent) { return React.cloneElement(renderContent(_props), makeChildProps()); } return ( ); }; const makeChildProps = () => { return { refreshValue, refreshType, progress, }; }; return ( {_renderContent()} ); }; export default RefreshControlContainer; const RefreshControlNormal = memo( function RefreshControlNormal({ refreshControlColor }) { return ( ); } ); const styles = StyleSheet.create({ baseControl: { alignItems: "center", flex: 1, justifyContent: "center", paddingTop: 10, }, container: { left: 0, position: "absolute", right: 0, width: "100%", }, textStyle: { marginTop: 4, fontSize: 13, textAlign: "center", }, });