mirror of
https://github.com/mudabbir-ahmad/Media-Aggregation-and-Sorting-System.git
synced 2026-10-07 19:40:20 +00:00
created a localised login system
This commit is contained in:
1 parent
59ac1fc926
commit
37511780b7
16 files changed
+3721
-20
No files matched your search
@@ -0,0 +1,642 @@
|
||||
import React, { useState } from 'react';
|
||||
import {
|
||||
StyleSheet,
|
||||
View,
|
||||
Text,
|
||||
ScrollView,
|
||||
TouchableOpacity,
|
||||
Alert,
|
||||
ActivityIndicator,
|
||||
Switch,
|
||||
TextInput,
|
||||
} from 'react-native';
|
||||
import DatabaseService from '../services/DatabaseService';
|
||||
import GoogleAUTH from '../AUTH/GoogleAUTH';
|
||||
import IOSAUTH from '../AUTH/IOSAUTH';
|
||||
import NASAUTH from '../AUTH/NASAUTH';
|
||||
|
||||
const OnboardingScreen = ({ navigation, route }) => {
|
||||
const { userId } = route.params;
|
||||
const [currentStep, setCurrentStep] = useState(0);
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
// Service selections
|
||||
const [googleEnabled, setGoogleEnabled] = useState(false);
|
||||
const [iosEnabled, setIosEnabled] = useState(false);
|
||||
const [nasEnabled, setNasEnabled] = useState(false);
|
||||
|
||||
// NAS configuration
|
||||
const [nasHost, setNasHost] = useState('');
|
||||
const [nasPort, setNasPort] = useState('22');
|
||||
const [nasUsername, setNasUsername] = useState('');
|
||||
const [nasPassword, setNasPassword] = useState('');
|
||||
const [nasPhotoFolder, setNasPhotoFolder] = useState('/home/user/photos');
|
||||
|
||||
// Default service selection
|
||||
const [defaultService, setDefaultService] = useState(null);
|
||||
|
||||
const steps = [
|
||||
{
|
||||
title: 'Select Services',
|
||||
description: 'Choose which services to enable (you can enable 1-3)',
|
||||
},
|
||||
{
|
||||
title: 'Configure Services',
|
||||
description: 'Set up the enabled services',
|
||||
},
|
||||
{
|
||||
title: 'Choose Default Service',
|
||||
description: 'Select which service to use for uploads by default',
|
||||
},
|
||||
];
|
||||
|
||||
const getEnabledServices = () => {
|
||||
const services = [];
|
||||
if (googleEnabled) services.push('Google Photos');
|
||||
if (iosEnabled) services.push('iCloud Photos');
|
||||
if (nasEnabled) services.push('NAS');
|
||||
return services;
|
||||
};
|
||||
|
||||
const handleGoogleAuth = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const googleAuth = new GoogleAUTH();
|
||||
// In a real app, this would trigger OAuth flow
|
||||
const result = await googleAuth.authenticate('auth_code');
|
||||
|
||||
await DatabaseService.linkAccount(
|
||||
userId,
|
||||
'GOOGLE_PHOTOS',
|
||||
{
|
||||
accessToken: result.accessToken,
|
||||
email: 'user@gmail.com',
|
||||
},
|
||||
defaultService === 'GOOGLE_PHOTOS'
|
||||
);
|
||||
|
||||
Alert.alert('Success', 'Google Photos connected!');
|
||||
} catch (error) {
|
||||
Alert.alert('Error', 'Failed to connect Google Photos: ' + error.message);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleIosAuth = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const iosAuth = new IOSAUTH();
|
||||
const result = await iosAuth.authenticate('icloud_user', 'icloud_password');
|
||||
|
||||
await DatabaseService.linkAccount(
|
||||
userId,
|
||||
'ICLOUD_PHOTOS',
|
||||
{
|
||||
accessToken: result.accessToken,
|
||||
email: 'user@icloud.com',
|
||||
},
|
||||
defaultService === 'ICLOUD_PHOTOS'
|
||||
);
|
||||
|
||||
Alert.alert('Success', 'iCloud Photos connected!');
|
||||
} catch (error) {
|
||||
Alert.alert('Error', 'Failed to connect iCloud Photos: ' + error.message);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleNasAuth = async () => {
|
||||
if (!nasHost || !nasUsername || !nasPassword) {
|
||||
Alert.alert('Error', 'Please fill in all NAS connection details');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
setLoading(true);
|
||||
const nasAuth = new NASAUTH();
|
||||
const result = await nasAuth.authenticate(
|
||||
nasHost,
|
||||
parseInt(nasPort) || 22,
|
||||
nasUsername,
|
||||
nasPassword
|
||||
);
|
||||
|
||||
await DatabaseService.linkAccount(
|
||||
userId,
|
||||
'NAS',
|
||||
{
|
||||
host: nasHost,
|
||||
port: nasPort,
|
||||
username: nasUsername,
|
||||
photoFolder: nasPhotoFolder,
|
||||
},
|
||||
defaultService === 'NAS'
|
||||
);
|
||||
|
||||
Alert.alert('Success', 'NAS connected!');
|
||||
} catch (error) {
|
||||
Alert.alert('Error', 'Failed to connect NAS: ' + error.message);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleNext = async () => {
|
||||
if (currentStep === 0) {
|
||||
const enabledCount = getEnabledServices().length;
|
||||
if (enabledCount === 0) {
|
||||
Alert.alert('Error', 'Please select at least one service');
|
||||
return;
|
||||
}
|
||||
if (enabledCount > 3) {
|
||||
Alert.alert('Error', 'You can enable a maximum of 3 services');
|
||||
return;
|
||||
}
|
||||
setCurrentStep(1);
|
||||
} else if (currentStep === 1) {
|
||||
// Configure services
|
||||
try {
|
||||
setLoading(true);
|
||||
if (googleEnabled) await handleGoogleAuth();
|
||||
if (iosEnabled) await handleIosAuth();
|
||||
if (nasEnabled) await handleNasAuth();
|
||||
setCurrentStep(2);
|
||||
} catch (error) {
|
||||
console.error('Configuration error:', error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
} else if (currentStep === 2) {
|
||||
// Complete onboarding
|
||||
if (!defaultService) {
|
||||
Alert.alert('Error', 'Please select a default service');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
setLoading(true);
|
||||
// Set default service
|
||||
const accounts = await DatabaseService.getLinkedAccounts(userId);
|
||||
const defaultAccount = accounts.find(
|
||||
(acc) => acc.service_type === defaultService
|
||||
);
|
||||
if (defaultAccount) {
|
||||
await DatabaseService.setDefaultService(userId, defaultAccount.id);
|
||||
}
|
||||
|
||||
// Navigate to home screen
|
||||
navigation.replace('Home', { userId });
|
||||
} catch (error) {
|
||||
Alert.alert('Error', 'Failed to complete setup: ' + error.message);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleBack = () => {
|
||||
if (currentStep > 0) {
|
||||
setCurrentStep(currentStep - 1);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<ScrollView style={styles.content} showsVerticalScrollIndicator={false}>
|
||||
<View style={styles.header}>
|
||||
<Text style={styles.stepIndicator}>
|
||||
Step {currentStep + 1} of {steps.length}
|
||||
</Text>
|
||||
<Text style={styles.title}>{steps[currentStep].title}</Text>
|
||||
<Text style={styles.description}>
|
||||
{steps[currentStep].description}
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
{currentStep === 0 && (
|
||||
<View style={styles.servicesContainer}>
|
||||
<ServiceCard
|
||||
name="Google Photos"
|
||||
enabled={googleEnabled}
|
||||
onToggle={() => setGoogleEnabled(!googleEnabled)}
|
||||
icon="📷"
|
||||
description="Connect to your Google Photos account"
|
||||
/>
|
||||
<ServiceCard
|
||||
name="iCloud Photos"
|
||||
enabled={iosEnabled}
|
||||
onToggle={() => setIosEnabled(!iosEnabled)}
|
||||
icon="🍎"
|
||||
description="Connect to your iCloud Photos account"
|
||||
/>
|
||||
<ServiceCard
|
||||
name="Network Storage (NAS)"
|
||||
enabled={nasEnabled}
|
||||
onToggle={() => setNasEnabled(!nasEnabled)}
|
||||
icon="💾"
|
||||
description="Connect to your Ubuntu NAS via SFTP"
|
||||
/>
|
||||
</View>
|
||||
)}
|
||||
|
||||
{currentStep === 1 && (
|
||||
<View style={styles.configContainer}>
|
||||
{googleEnabled && (
|
||||
<ServiceConfigCard
|
||||
title="Google Photos"
|
||||
onPress={handleGoogleAuth}
|
||||
loading={loading}
|
||||
>
|
||||
<Text style={styles.configText}>
|
||||
Tap to authenticate with your Google account
|
||||
</Text>
|
||||
</ServiceConfigCard>
|
||||
)}
|
||||
|
||||
{iosEnabled && (
|
||||
<ServiceConfigCard
|
||||
title="iCloud Photos"
|
||||
onPress={handleIosAuth}
|
||||
loading={loading}
|
||||
>
|
||||
<Text style={styles.configText}>
|
||||
Tap to authenticate with your Apple account
|
||||
</Text>
|
||||
</ServiceConfigCard>
|
||||
)}
|
||||
|
||||
{nasEnabled && (
|
||||
<ServiceConfigCard title="Network Storage (NAS)" loading={loading}>
|
||||
<Text style={styles.configLabel}>Server Address</Text>
|
||||
<TextInput
|
||||
style={styles.configInput}
|
||||
placeholder="192.168.1.100 or nas.example.com"
|
||||
value={nasHost}
|
||||
onChangeText={setNasHost}
|
||||
editable={!loading}
|
||||
placeholderTextColor="#999"
|
||||
/>
|
||||
|
||||
<Text style={styles.configLabel}>Port</Text>
|
||||
<TextInput
|
||||
style={styles.configInput}
|
||||
placeholder="22"
|
||||
value={nasPort}
|
||||
onChangeText={setNasPort}
|
||||
editable={!loading}
|
||||
keyboardType="numeric"
|
||||
placeholderTextColor="#999"
|
||||
/>
|
||||
|
||||
<Text style={styles.configLabel}>Username</Text>
|
||||
<TextInput
|
||||
style={styles.configInput}
|
||||
placeholder="SSH username"
|
||||
value={nasUsername}
|
||||
onChangeText={setNasUsername}
|
||||
editable={!loading}
|
||||
autoCapitalize="none"
|
||||
placeholderTextColor="#999"
|
||||
/>
|
||||
|
||||
<Text style={styles.configLabel}>Password</Text>
|
||||
<TextInput
|
||||
style={styles.configInput}
|
||||
placeholder="SSH password"
|
||||
value={nasPassword}
|
||||
onChangeText={setNasPassword}
|
||||
editable={!loading}
|
||||
secureTextEntry
|
||||
autoCapitalize="none"
|
||||
placeholderTextColor="#999"
|
||||
/>
|
||||
|
||||
<Text style={styles.configLabel}>Photos Folder Path</Text>
|
||||
<TextInput
|
||||
style={styles.configInput}
|
||||
placeholder="/home/user/photos"
|
||||
value={nasPhotoFolder}
|
||||
onChangeText={setNasPhotoFolder}
|
||||
editable={!loading}
|
||||
placeholderTextColor="#999"
|
||||
/>
|
||||
|
||||
<TouchableOpacity
|
||||
style={[styles.testButton, loading && styles.buttonDisabled]}
|
||||
onPress={handleNasAuth}
|
||||
disabled={loading}
|
||||
>
|
||||
{loading ? (
|
||||
<ActivityIndicator color="#fff" />
|
||||
) : (
|
||||
<Text style={styles.buttonText}>Test Connection</Text>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
</ServiceConfigCard>
|
||||
)}
|
||||
</View>
|
||||
)}
|
||||
|
||||
{currentStep === 2 && (
|
||||
<View style={styles.defaultServiceContainer}>
|
||||
<Text style={styles.defaultServiceTitle}>
|
||||
Select your default upload service:
|
||||
</Text>
|
||||
{getEnabledServices().map((service) => (
|
||||
<ServiceSelectCard
|
||||
key={service}
|
||||
service={service}
|
||||
selected={defaultService === service}
|
||||
onSelect={() => {
|
||||
const serviceTypeMap = {
|
||||
'Google Photos': 'GOOGLE_PHOTOS',
|
||||
'iCloud Photos': 'ICLOUD_PHOTOS',
|
||||
NAS: 'NAS',
|
||||
};
|
||||
setDefaultService(serviceTypeMap[service]);
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</View>
|
||||
)}
|
||||
</ScrollView>
|
||||
|
||||
<View style={styles.footer}>
|
||||
<TouchableOpacity
|
||||
style={[styles.footerButton, currentStep === 0 && styles.hidden]}
|
||||
onPress={handleBack}
|
||||
disabled={loading}
|
||||
>
|
||||
<Text style={styles.footerButtonText}>Back</Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
<TouchableOpacity
|
||||
style={[styles.footerButton, styles.nextButton, loading && styles.buttonDisabled]}
|
||||
onPress={handleNext}
|
||||
disabled={loading}
|
||||
>
|
||||
{loading ? (
|
||||
<ActivityIndicator color="#fff" />
|
||||
) : (
|
||||
<Text style={styles.footerButtonText}>
|
||||
{currentStep === steps.length - 1 ? 'Complete' : 'Next'}
|
||||
</Text>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const ServiceCard = ({ name, enabled, onToggle, icon, description }) => (
|
||||
<View style={styles.serviceCard}>
|
||||
<View style={styles.serviceCardContent}>
|
||||
<Text style={styles.serviceIcon}>{icon}</Text>
|
||||
<View style={styles.serviceInfo}>
|
||||
<Text style={styles.serviceName}>{name}</Text>
|
||||
<Text style={styles.serviceDescription}>{description}</Text>
|
||||
</View>
|
||||
</View>
|
||||
<Switch value={enabled} onValueChange={onToggle} />
|
||||
</View>
|
||||
);
|
||||
|
||||
const ServiceConfigCard = ({ title, onPress, loading, children }) => (
|
||||
<View style={styles.configCard}>
|
||||
<Text style={styles.configCardTitle}>{title}</Text>
|
||||
{onPress && (
|
||||
<TouchableOpacity
|
||||
style={[styles.configButton, loading && styles.buttonDisabled]}
|
||||
onPress={onPress}
|
||||
disabled={loading}
|
||||
>
|
||||
{loading ? (
|
||||
<ActivityIndicator color="#fff" />
|
||||
) : (
|
||||
<Text style={styles.buttonText}>Authenticate</Text>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
{children}
|
||||
</View>
|
||||
);
|
||||
|
||||
const ServiceSelectCard = ({ service, selected, onSelect }) => (
|
||||
<TouchableOpacity
|
||||
style={[styles.selectCard, selected && styles.selectedCard]}
|
||||
onPress={onSelect}
|
||||
>
|
||||
<View style={[styles.radioButton, selected && styles.radioSelected]} />
|
||||
<Text style={[styles.selectText, selected && styles.selectedText]}>
|
||||
{service}
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: '#f5f5f5',
|
||||
},
|
||||
content: {
|
||||
flex: 1,
|
||||
paddingHorizontal: 20,
|
||||
paddingTop: 20,
|
||||
},
|
||||
header: {
|
||||
marginBottom: 30,
|
||||
},
|
||||
stepIndicator: {
|
||||
fontSize: 12,
|
||||
color: '#007AFF',
|
||||
fontWeight: '600',
|
||||
marginBottom: 8,
|
||||
},
|
||||
title: {
|
||||
fontSize: 28,
|
||||
fontWeight: 'bold',
|
||||
color: '#333',
|
||||
marginBottom: 8,
|
||||
},
|
||||
description: {
|
||||
fontSize: 16,
|
||||
color: '#666',
|
||||
},
|
||||
servicesContainer: {
|
||||
marginBottom: 20,
|
||||
},
|
||||
serviceCard: {
|
||||
backgroundColor: '#fff',
|
||||
borderRadius: 12,
|
||||
padding: 16,
|
||||
marginBottom: 12,
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
borderWidth: 1,
|
||||
borderColor: '#e0e0e0',
|
||||
},
|
||||
serviceCardContent: {
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
},
|
||||
serviceIcon: {
|
||||
fontSize: 32,
|
||||
marginRight: 16,
|
||||
},
|
||||
serviceInfo: {
|
||||
flex: 1,
|
||||
},
|
||||
serviceName: {
|
||||
fontSize: 16,
|
||||
fontWeight: '600',
|
||||
color: '#333',
|
||||
marginBottom: 4,
|
||||
},
|
||||
serviceDescription: {
|
||||
fontSize: 13,
|
||||
color: '#999',
|
||||
},
|
||||
configContainer: {
|
||||
marginBottom: 20,
|
||||
},
|
||||
configCard: {
|
||||
backgroundColor: '#fff',
|
||||
borderRadius: 12,
|
||||
padding: 16,
|
||||
marginBottom: 16,
|
||||
borderWidth: 1,
|
||||
borderColor: '#e0e0e0',
|
||||
},
|
||||
configCardTitle: {
|
||||
fontSize: 16,
|
||||
fontWeight: '600',
|
||||
color: '#333',
|
||||
marginBottom: 12,
|
||||
},
|
||||
configLabel: {
|
||||
fontSize: 14,
|
||||
fontWeight: '600',
|
||||
color: '#333',
|
||||
marginTop: 12,
|
||||
marginBottom: 6,
|
||||
},
|
||||
configInput: {
|
||||
borderWidth: 1,
|
||||
borderColor: '#ddd',
|
||||
borderRadius: 8,
|
||||
paddingHorizontal: 12,
|
||||
paddingVertical: 10,
|
||||
fontSize: 14,
|
||||
backgroundColor: '#f9f9f9',
|
||||
color: '#333',
|
||||
},
|
||||
configText: {
|
||||
fontSize: 14,
|
||||
color: '#666',
|
||||
marginTop: 12,
|
||||
},
|
||||
configButton: {
|
||||
backgroundColor: '#007AFF',
|
||||
borderRadius: 8,
|
||||
paddingVertical: 10,
|
||||
paddingHorizontal: 16,
|
||||
alignItems: 'center',
|
||||
},
|
||||
testButton: {
|
||||
backgroundColor: '#34C759',
|
||||
borderRadius: 8,
|
||||
paddingVertical: 10,
|
||||
paddingHorizontal: 16,
|
||||
alignItems: 'center',
|
||||
marginTop: 16,
|
||||
},
|
||||
buttonDisabled: {
|
||||
opacity: 0.6,
|
||||
},
|
||||
buttonText: {
|
||||
color: '#fff',
|
||||
fontSize: 14,
|
||||
fontWeight: '600',
|
||||
},
|
||||
defaultServiceContainer: {
|
||||
marginBottom: 20,
|
||||
},
|
||||
defaultServiceTitle: {
|
||||
fontSize: 16,
|
||||
fontWeight: '600',
|
||||
color: '#333',
|
||||
marginBottom: 12,
|
||||
},
|
||||
selectCard: {
|
||||
backgroundColor: '#fff',
|
||||
borderRadius: 12,
|
||||
padding: 16,
|
||||
marginBottom: 12,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
borderWidth: 2,
|
||||
borderColor: '#ddd',
|
||||
},
|
||||
selectedCard: {
|
||||
borderColor: '#007AFF',
|
||||
backgroundColor: '#f0f7ff',
|
||||
},
|
||||
radioButton: {
|
||||
width: 20,
|
||||
height: 20,
|
||||
borderRadius: 10,
|
||||
borderWidth: 2,
|
||||
borderColor: '#ddd',
|
||||
marginRight: 12,
|
||||
},
|
||||
radioSelected: {
|
||||
borderColor: '#007AFF',
|
||||
backgroundColor: '#007AFF',
|
||||
},
|
||||
selectText: {
|
||||
fontSize: 16,
|
||||
color: '#333',
|
||||
},
|
||||
selectedText: {
|
||||
color: '#007AFF',
|
||||
fontWeight: '600',
|
||||
},
|
||||
footer: {
|
||||
flexDirection: 'row',
|
||||
paddingHorizontal: 20,
|
||||
paddingVertical: 16,
|
||||
borderTopWidth: 1,
|
||||
borderTopColor: '#e0e0e0',
|
||||
gap: 12,
|
||||
},
|
||||
footerButton: {
|
||||
flex: 1,
|
||||
paddingVertical: 12,
|
||||
paddingHorizontal: 16,
|
||||
borderRadius: 8,
|
||||
alignItems: 'center',
|
||||
backgroundColor: '#fff',
|
||||
borderWidth: 1,
|
||||
borderColor: '#ddd',
|
||||
},
|
||||
nextButton: {
|
||||
backgroundColor: '#007AFF',
|
||||
borderColor: '#007AFF',
|
||||
},
|
||||
footerButtonText: {
|
||||
fontSize: 16,
|
||||
fontWeight: '600',
|
||||
color: '#333',
|
||||
},
|
||||
hidden: {
|
||||
opacity: 0,
|
||||
pointerEvents: 'none',
|
||||
},
|
||||
});
|
||||
|
||||
export default OnboardingScreen;
|
||||
|
||||
Reference in new issue
Block a user