2026-07-03 13:10:46 +05:30

180 lines
4.5 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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>
);
}