Skip to content

Instantly share code, notes, and snippets.

@Yasir5247
Created June 22, 2023 10:15
Show Gist options
  • Save Yasir5247/911572ae4e13780fcaae4153e06c6acf to your computer and use it in GitHub Desktop.
Save Yasir5247/911572ae4e13780fcaae4153e06c6acf to your computer and use it in GitHub Desktop.
sumsub face verification
import React, {useEffect, useRef, useState} from 'react';
import {Alert, StyleSheet} from 'react-native';
import {View, Text} from 'react-native-ui-lib';
import {NavigationFunctionComponent} from 'react-native-navigation';
import {observer} from 'mobx-react';
//lottie
import LottieView from 'lottie-react-native';
import {lotties} from '../../assets/lotties';
//navigation
import {useNavigationButtonPress} from 'react-native-navigation-hooks/dist';
//@ts-ignore
import SNSMobileSDK from '@sumsub/react-native-mobilesdk-module';
//services
import {useStyles} from '../../hooks/useStyles';
import {useServices} from '../../services';
import {useStores} from '../../stores';
import {useClearCache} from '../../hooks/useClearCache';
import {captureException, captureMessage} from '../../utils/sentry';
//types and hooks
import {SumSubStatus} from '../../models/sumsub';
import {useCommonFuncs} from '../../hooks/useComonFuncs';
import {getSecureValue} from '../../utils/getToken';
import {useSumsub} from '../../hooks/useSumSub';
//components
import {BeeModal} from '../../components/ui/BeeModal';
import {QuitModalContent} from '../../components/modalContent/quitModal';
import {ScreenBackground} from '../../components/common/backgrounds/ScreenBackground';
import {WhiteButton} from '../../components/ui/whiteButton';
import {GetStartedBullets} from '../../components/common/textRows/getStartedBullets';
export const FaceRecogStartScreen: NavigationFunctionComponent = observer(
({componentId}) => {
//services and hooks
const {nav, t} = useServices();
const {userProfile} = useStores();
const LStyle = useStyles();
//custom hooks
const {hardClearCache, loading} = useClearCache();
const {createFaceAuthEvent} = useCommonFuncs();
//state
const [isLoading, setIsloading] = useState<boolean>(false);
//ref
const quitModalRef = useRef<any>(null);
//custom hooks
const {handleCreateSumSubApplicant} = useSumsub();
//handle backbuttion
useNavigationButtonPress(({buttonId, componentId}) => {
switch (buttonId) {
case 'RNN.hardwareBackButton':
quitModalRef.current.open();
break;
default:
break;
}
}, componentId);
const showAlert = async (message: string) => {
Alert.alert('Alert', message, [
{
text: 'OK',
onPress: async () => {
await hardClearCache();
setIsloading(false);
},
},
]);
};
const handleTokenExpiration = async () => {
/*
This is a token expiration handler, will be called if
the provided token is invalid or got expired
call your backend to fetch a new access token (this is just an example)
*/
try {
const res = await handleCreateSumSubApplicant();
return res.token;
} catch (error) {
console.log('error', error);
captureException(error);
}
};
const handleStatusChanged = (event: any) => {
console.log('onStatusChanged_prev_stat', event.prevStatus);
console.log('onStatusChanged_new_stat', event.newStatus);
if (
event.prevStatus === SumSubStatus.ready &&
event.newStatus === SumSubStatus.incomplete
) {
captureMessage(event);
showAlert(t.do('section.faceRecog.status.incomplete'));
}
};
const handleLog = (event: any) => {
console.log('onLog_[Idensic]', JSON.stringify(event.message));
};
const handleEvent = (event: any) => {
console.log('onEvent', JSON.stringify(event));
};
const handleActionResult = (result: any) => {
try {
console.log('handleActionResult', JSON.stringify(result, null, 2));
if (result.answer === 'RED') {
userProfile.setFaceVerified(false);
nav.push(componentId, 'FaceRecogErrorScreen');
}
return Promise.resolve('continue');
} catch (error) {
// Handle any unexpected errors
console.log('handleActionResult error:', error);
captureException(error);
setIsloading(false);
// Optionally, reject the promise with the error
return Promise.reject(error);
}
};
const handleResult = async (result: any) => {
try {
console.log('handleResultFunction', JSON.stringify(result, null, 2));
if (result.status === SumSubStatus.pending) {
setIsloading(false);
nav.push(componentId, 'FaceRecogWaitScreen');
} else if (result.status === SumSubStatus.incomplete) {
setIsloading(false);
quitModalRef.current.open();
} else if (result.status === SumSubStatus.approved) {
setIsloading(false);
nav.start();
} else if (result.actionResult.answer === 'GREEN') {
setIsloading(false);
userProfile.setFaceVerified(true);
nav.start();
} else {
setIsloading(false);
nav.push(componentId, 'FaceRecogErrorScreen');
}
} catch (error) {
console.log('handleResult error:', error);
captureException(error);
}
};
const launchSNSMobileSDK = async () => {
setIsloading(true);
try {
const sumSubToken = await getSecureValue('sumSubToken');
let snsMobileSDK = SNSMobileSDK.init(sumSubToken, handleTokenExpiration)
.withHandlers({
onStatusChanged: handleStatusChanged,
onLog: handleLog,
onEvent: handleEvent,
onActionResult: handleActionResult,
})
.withDebug(false)
.withLocale('en')
.build();
const result = await snsMobileSDK.launch();
console.log('result', result);
if (!result) {
showAlert(t.do('section.errors.sumSubUploadError'));
setIsloading(false);
}
await handleResult(result);
} catch (error) {
console.log('error', error);
setIsloading(false);
showAlert(t.do('section.errors.sumSubUploadError'));
captureException(error);
}
};
return (
<ScreenBackground>
<View center height={'50%'}>
<View marginT-50 width={'80%'} height={'80%'}>
<LottieView
style={{flex: 1}}
source={lotties.faceVerification}
autoSize={false}
resizeMode="cover"
autoPlay
loop
/>
</View>
</View>
<View height={'50%'} bg-bgCard style={styles.bottom}>
<View flex-1 paddingV-30 paddingH-30 style={styles.border}>
<View>
<Text style={LStyle.sliderDesTitle}>
{t.do('section.faceRecog.title')}
</Text>
</View>
<View marginT-10>
<GetStartedBullets
number={1}
data={t.do('section.faceRecog.screen.startScreen.bullets.one')}
/>
<GetStartedBullets
number={2}
data={t.do('section.faceRecog.screen.startScreen.bullets.two')}
/>
<GetStartedBullets
number={3}
data={t.do(
'section.faceRecog.screen.startScreen.bullets.three',
)}
/>
</View>
</View>
<View paddingH-30 paddingV-10 style={styles.border}>
<WhiteButton
title={t.do('section.buttons.getStarted')}
loadingStatus={isLoading}
onPress={launchSNSMobileSDK}
/>
<WhiteButton
title={t.do('section.buttons.cancel')}
loadingStatus={loading}
onPress={async () => quitModalRef.current.open()}
/>
</View>
</View>
<BeeModal heading={''} modalRef={quitModalRef} modalHeight={350}>
<View flex-1 style={{borderWidth: 0, borderColor: '#000'}}>
<QuitModalContent
onPressQuit={async () => {
await hardClearCache();
}}
onPressStay={() => quitModalRef.current.close()}
/>
</View>
</BeeModal>
</ScreenBackground>
);
},
);
FaceRecogStartScreen.options = {
bottomTabs: {
visible: false,
drawBehind: true,
},
topBar: {
visible: false,
},
hardwareBackButton: {
popStackOnPress: false,
},
};
const styles = StyleSheet.create({
border: {
borderWidth: 0,
borderColor: '#000',
},
bottom: {
flex: 1,
padding: 10,
borderTopRightRadius: 12,
borderTopLeftRadius: 12,
},
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment