import { observer } from "mobx-react-lite"; import React, { useEffect, useRef } from "react"; import { RefreshControl, ScrollView, ScrollViewProps } from "react-native"; import { HScrollView } from "react-native-head-tab-view"; import { KeyboardAwareScrollView } from "react-native-keyboard-aware-scroll-view"; import Animated, { runOnJS, useAnimatedStyle, withTiming, } from "react-native-reanimated"; import { Platform_iOS, useColors, useDimensions, useMeasure, useReanimatedValue, useSafeArea, vs, } from "../commons"; import { KeyboardProps, Spinner, View } from "../components"; import { tBaseStore } from "../store"; export type ScrollProps = ScrollViewProps & { refScrollView?: any; reanimated?: boolean; isRefreshing?: boolean; hideOverflow?: boolean; showIndicator?: boolean; awareKeyboard?: boolean; hViewIndex?: number; onRefreshing?: () => void; }; const AScrollView = Animated.createAnimatedComponent(ScrollView); const AHScrollView = Animated.createAnimatedComponent(HScrollView); const AKeyboardAwareScrollView = Animated.createAnimatedComponent( KeyboardAwareScrollView ); export const Scroll = observer((props: ScrollProps) => { const { refScrollView, reanimated, isRefreshing, hideOverflow, showIndicator, awareKeyboard, hViewIndex, children, contentContainerStyle, onRefreshing, } = props; const enableRefresh = typeof isRefreshing === "boolean"; const colors = useColors(); const renderRefresh = () => { if (!enableRefresh) return undefined; return ( ); }; const renderRefreshControl = () => { return ; }; const MyScroll = typeof hViewIndex === "number" ? reanimated ? AHScrollView : HScrollView : awareKeyboard && Platform_iOS ? reanimated ? AKeyboardAwareScrollView : KeyboardAwareScrollView : reanimated ? AScrollView : ScrollView; return ( {children} ); }); export const ScrollKeyboard = (props: ScrollProps & KeyboardProps) => { const { bottom } = useSafeArea(); const { awareKeyboard, before = bottom, after = vs(16), enableAndroid, onShow, onHide, } = props; const { height, keyboard, duration } = useDimensions(true); const [refView, measureView] = useMeasure(duration); const v1H = useReanimatedValue(Platform_iOS ? before : after); const v2H = useReanimatedValue(0); const yOffsetValue = useRef(0); const callback = (show: boolean) => { show ? onShow?.() : onHide?.(); }; const onLayout = () => { measureView(({ y }) => { if (y && !keyboard) yOffsetValue.current = Math.max(0, height - y); }); }; useEffect(() => { if (Platform_iOS || enableAndroid) { v1H.value = withTiming( keyboard ? after : before, { duration, }, (finished) => { finished && runOnJS(callback)(!!keyboard); } ); if (awareKeyboard) return; v2H.value = withTiming(keyboard ? keyboard - yOffsetValue.current : 0, { duration, }); } else callback(!!keyboard); }, [before, after, enableAndroid, onShow, onHide, keyboard, duration]); const v1S = useAnimatedStyle( () => ({ height: v1H.value, }), [] ); const v2S = useAnimatedStyle( () => ({ height: v2H.value, }), [] ); return ( <> {props.children} ); };