180 lines
4.5 KiB
TypeScript
180 lines
4.5 KiB
TypeScript
import React, {
|
||
useCallback,
|
||
useEffect,
|
||
useState,
|
||
} from 'react';
|
||
import { ActivityIndicator, View, Alert, Platform, PermissionsAndroid } from 'react-native';
|
||
import {WebView} from 'react-native-webview';
|
||
import { styles } from './wrapper.styles';
|
||
import {urls} from '@config'
|
||
import { WrapperProps } from './wrapper.props';
|
||
import BootSplash from 'react-native-bootsplash';
|
||
import keychainService from '../../services/keychainService';
|
||
import storageService from '../../services/storageService';
|
||
import biometricService from '../../services/biometricService';
|
||
import useBiometric from '../../hooks/useBiometric';
|
||
import { LoginScreen, SignupScreen, ForgotPasswordScreen } from '@features';
|
||
|
||
|
||
export function Wrapper({ style }: WrapperProps) {
|
||
const [loading, setLoading] = useState(true);
|
||
const [authenticated, setAuthenticated] = useState(false);
|
||
const [currentScreen, setCurrentScreen] = useState<'login' | 'signup' | 'forgotPassword'>('login');
|
||
|
||
const { authenticate } = useBiometric();
|
||
|
||
const handleAuthSuccess = useCallback(async (token: string) => {
|
||
await keychainService.saveToken(token);
|
||
|
||
try {
|
||
const bioAvailability = await biometricService.isAvailable();
|
||
if (bioAvailability.available) {
|
||
Alert.alert(
|
||
'Enable Biometric Login',
|
||
`Would you like to enable ${bioAvailability.biometryType} login for faster access next time?`,
|
||
[
|
||
{
|
||
text: 'No',
|
||
onPress: () => setAuthenticated(true),
|
||
style: 'cancel',
|
||
},
|
||
{
|
||
text: 'Yes',
|
||
onPress: async () => {
|
||
await storageService.setBiometricEnabled(true);
|
||
setAuthenticated(true);
|
||
},
|
||
},
|
||
],
|
||
{ cancelable: false }
|
||
);
|
||
} else {
|
||
setAuthenticated(true);
|
||
}
|
||
} catch (error) {
|
||
console.log('Error checking biometric availability during login:', error);
|
||
setAuthenticated(true);
|
||
}
|
||
}, []);
|
||
|
||
const initialize = useCallback(async () => {
|
||
try {
|
||
const token = await keychainService.getToken();
|
||
|
||
if (!token) {
|
||
// No token – render LoginScreen later
|
||
setAuthenticated(false);
|
||
setLoading(false);
|
||
return;
|
||
}
|
||
|
||
const biometricEnabled =
|
||
await storageService.isBiometricEnabled();
|
||
|
||
if (!biometricEnabled) {
|
||
setAuthenticated(true);
|
||
|
||
return;
|
||
}
|
||
|
||
const success = await authenticate();
|
||
|
||
if (success) {
|
||
setAuthenticated(true);
|
||
}
|
||
} finally {
|
||
setLoading(false);
|
||
|
||
BootSplash.hide({
|
||
fade: true,
|
||
});
|
||
}
|
||
}, [authenticate]);
|
||
|
||
useEffect(() => {
|
||
initialize();
|
||
}, [initialize]);
|
||
|
||
useEffect(() => {
|
||
if (authenticated) {
|
||
const requestPermissions = async () => {
|
||
if (Platform.OS === 'android') {
|
||
try {
|
||
await PermissionsAndroid.requestMultiple([
|
||
PermissionsAndroid.PERMISSIONS.RECORD_AUDIO,
|
||
PermissionsAndroid.PERMISSIONS.CAMERA,
|
||
]);
|
||
} catch (err) {
|
||
console.warn(err);
|
||
}
|
||
}
|
||
};
|
||
requestPermissions();
|
||
}
|
||
}, [authenticated]);
|
||
|
||
if (loading) {
|
||
return (
|
||
<View style={styles.loadingContainer}>
|
||
<ActivityIndicator size="large" color="red" />
|
||
</View>
|
||
);
|
||
}
|
||
|
||
if (!authenticated) {
|
||
if (currentScreen === 'signup') {
|
||
return (
|
||
<SignupScreen
|
||
onSignupSuccess={handleAuthSuccess}
|
||
onSignInPress={() => {
|
||
setCurrentScreen('login');
|
||
}}
|
||
/>
|
||
);
|
||
}
|
||
|
||
if (currentScreen === 'forgotPassword') {
|
||
return (
|
||
<ForgotPasswordScreen
|
||
onSendCode={(emailOrPhone) => {
|
||
// Alert removed
|
||
setCurrentScreen('login');
|
||
}}
|
||
onSignInPress={() => {
|
||
setCurrentScreen('login');
|
||
}}
|
||
/>
|
||
);
|
||
}
|
||
|
||
return (
|
||
<LoginScreen
|
||
onLoginSuccess={handleAuthSuccess}
|
||
onForgotPassword={() => {
|
||
setCurrentScreen('forgotPassword');
|
||
}}
|
||
onCreateAccount={() => {
|
||
setCurrentScreen('signup');
|
||
}}
|
||
/>
|
||
);
|
||
}
|
||
|
||
return (
|
||
<View style={[styles.container, style]}>
|
||
<WebView
|
||
source={{ uri: urls.webUrl }}
|
||
style={styles.webview}
|
||
originWhitelist={['*']}
|
||
javaScriptEnabled={true}
|
||
domStorageEnabled={true}
|
||
allowsInlineMediaPlayback
|
||
mediaPlaybackRequiresUserAction={false}
|
||
allowFileAccess={true}
|
||
allowUniversalAccessFromFileURLs={true}
|
||
allowFileAccessFromFileURLs={true}
|
||
/>
|
||
</View>
|
||
);
|
||
}
|