@nghinv/react-native-app-tour
Version:
React Native app tour Library
132 lines (119 loc) • 3.59 kB
JavaScript
/**
* Created by nghinv on Wed Jun 23 2021
* Copyright (c) 2021 nghinv@lumi.biz
*/
import React, { forwardRef, useImperativeHandle, useState, useContext, useCallback, useRef, useEffect } from 'react';
import equals from 'react-fast-compare';
import { Keyboard, Modal, BackHandler } from 'react-native';
import { useSharedValue, withTiming, runOnJS } from 'react-native-reanimated';
import { AppTourContext } from './AppTourContext';
import { useEvent } from './hook';
import MashView from './MashView';
import { timingConfig } from './math';
function AppTourView(_, ref) {
const [visible, setVisible] = useState(false);
const {
nodes,
scenes,
sceneIndex,
options
} = useContext(AppTourContext);
const {
emitEvent
} = useEvent();
const progress = useSharedValue(0);
const currentStep = useSharedValue(0);
const backHandler = useRef();
const handleBackButton = () => {
if (options !== null && options !== void 0 && options.backAndroidToSkip) {
onStop();
}
return true;
};
const open = useCallback(step => {
var _scenes$sceneIndex;
Keyboard.dismiss();
backHandler.current = BackHandler.addEventListener('hardwareBackPress', handleBackButton);
if (((_scenes$sceneIndex = scenes[sceneIndex]) === null || _scenes$sceneIndex === void 0 ? void 0 : _scenes$sceneIndex.length) > 0) {
setVisible(true);
currentStep.value = step !== null && step !== void 0 ? step : 0;
progress.value = withTiming(1, timingConfig);
const scene = scenes[sceneIndex][currentStep.value];
emitEvent('AppTourEvent', {
name: 'onStart',
step: currentStep.value,
node: nodes.value.find(n => n.id === scene.id),
scene
});
}
}, [sceneIndex, scenes, backHandler]);
const onStop = useCallback(callback => {
if (backHandler.current) {
backHandler.current.remove();
}
progress.value = withTiming(0, timingConfig, () => {
runOnJS(setVisible)(false);
if (callback) {
runOnJS(callback)();
}
});
}, [backHandler]);
useEffect(() => {
return () => {
if (backHandler.current) {
backHandler.current.remove();
}
};
}, [backHandler]);
useImperativeHandle(ref, () => ({
nextStep: () => {
const nextValue = currentStep.value + 1;
const sceneLength = scenes[sceneIndex].length;
if (nextValue <= sceneLength - 1) {
currentStep.value = nextValue;
} else {
onStop();
}
},
preStep: () => {
const preValue = currentStep.value - 1;
if (preValue >= 0) {
currentStep.value = preValue;
} else {
onStop();
}
},
stop: cb => {
onStop(cb);
},
start: step => {
open(step);
},
currentStep: () => {
return currentStep.value;
}
}));
if (!visible) return null;
if (options !== null && options !== void 0 && options.nativeModal) {
return /*#__PURE__*/React.createElement(Modal, {
visible: visible,
transparent: true,
animationType: "none"
}, /*#__PURE__*/React.createElement(MashView, {
onStop: onStop,
open: open,
progress: progress,
currentStep: currentStep,
scene: scenes[sceneIndex]
}));
}
return /*#__PURE__*/React.createElement(MashView, {
onStop: onStop,
open: open,
progress: progress,
currentStep: currentStep,
scene: scenes[sceneIndex]
});
}
export default /*#__PURE__*/React.memo( /*#__PURE__*/forwardRef(AppTourView), equals);
//# sourceMappingURL=AppTourView.js.map