UNPKG

@stream-io/flat-list-mvcp

Version:

`maintainVisibleContentPosition` support for Android react-native

107 lines (92 loc) 4.95 kB
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } import React, { useEffect, useRef } from 'react'; import { FlatList, NativeModules, Platform } from 'react-native'; export const ScrollViewManager = NativeModules.MvcpScrollViewManager; export default /*#__PURE__*/React.forwardRef((props, forwardedRef) => { var _props$maintainVisibl, _props$maintainVisibl2; const flRef = useRef(null); const isMvcpEnabledNative = useRef(false); const handle = useRef(null); const enableMvcpRetriesCount = useRef(0); const isMvcpPropPresentRef = useRef(!!props.maintainVisibleContentPosition); const autoscrollToTopThreshold = useRef(((_props$maintainVisibl = props.maintainVisibleContentPosition) === null || _props$maintainVisibl === void 0 ? void 0 : _props$maintainVisibl.autoscrollToTopThreshold) || -Number.MAX_SAFE_INTEGER); const minIndexForVisible = useRef(((_props$maintainVisibl2 = props.maintainVisibleContentPosition) === null || _props$maintainVisibl2 === void 0 ? void 0 : _props$maintainVisibl2.minIndexForVisible) || 1); const retryTimeoutId = useRef(); const debounceTimeoutId = useRef(); const disableMvcpRef = useRef(async () => { isMvcpEnabledNative.current = false; if (!(handle !== null && handle !== void 0 && handle.current)) { return; } await ScrollViewManager.disableMaintainVisibleContentPosition(handle.current); }); const enableMvcpWithRetriesRef = useRef(() => { // debounce to wait till consecutive mvcp enabling // this ensures that always previous handles are disabled first if (debounceTimeoutId.current) { clearTimeout(debounceTimeoutId.current); } debounceTimeoutId.current = setTimeout(async () => { // disable any previous enabled handles await disableMvcpRef.current(); if (!flRef.current || !isMvcpPropPresentRef.current || isMvcpEnabledNative.current || Platform.OS !== 'android') { return; } const scrollableNode = flRef.current.getScrollableNode(); try { const _handle = await ScrollViewManager.enableMaintainVisibleContentPosition(scrollableNode, autoscrollToTopThreshold.current, minIndexForVisible.current); handle.current = _handle; } catch (error) { /** * enableMaintainVisibleContentPosition from native module may throw IllegalViewOperationException, * in case view is not ready yet. In that case, lets do a retry!! (max of 10 tries) */ if (enableMvcpRetriesCount.current < 10) { retryTimeoutId.current = setTimeout(enableMvcpWithRetriesRef.current, 100); enableMvcpRetriesCount.current += 1; } } }, 300); }); useEffect(() => { var _props$maintainVisibl3, _props$maintainVisibl4; // when the mvcp prop changes // enable natively again, if the prop has changed const propAutoscrollToTopThreshold = ((_props$maintainVisibl3 = props.maintainVisibleContentPosition) === null || _props$maintainVisibl3 === void 0 ? void 0 : _props$maintainVisibl3.autoscrollToTopThreshold) || -Number.MAX_SAFE_INTEGER; const propMinIndexForVisible = ((_props$maintainVisibl4 = props.maintainVisibleContentPosition) === null || _props$maintainVisibl4 === void 0 ? void 0 : _props$maintainVisibl4.minIndexForVisible) || 1; const hasMvcpChanged = autoscrollToTopThreshold.current !== propAutoscrollToTopThreshold || minIndexForVisible.current !== propMinIndexForVisible || isMvcpPropPresentRef.current !== !!props.maintainVisibleContentPosition; if (hasMvcpChanged) { enableMvcpRetriesCount.current = 0; autoscrollToTopThreshold.current = propAutoscrollToTopThreshold; minIndexForVisible.current = propMinIndexForVisible; isMvcpPropPresentRef.current = !!props.maintainVisibleContentPosition; enableMvcpWithRetriesRef.current(); } }, [props.maintainVisibleContentPosition]); const refCallback = useRef(ref => { flRef.current = ref; enableMvcpWithRetriesRef.current(); if (typeof forwardedRef === 'function') { forwardedRef(ref); } else if (forwardedRef) { forwardedRef.current = ref; } }).current; useEffect(() => { const disableMvcp = disableMvcpRef.current; return () => { // clean up the retry mechanism if (debounceTimeoutId.current) { clearTimeout(debounceTimeoutId.current); } // clean up any debounce if (debounceTimeoutId.current) { clearTimeout(debounceTimeoutId.current); } disableMvcp(); }; }, []); return /*#__PURE__*/React.createElement(FlatList, _extends({}, props, { ref: refCallback })); }); //# sourceMappingURL=FlatList.android.js.map