@oxyhq/services 5.4.1 → 5.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/commonjs/assets/icons/OxyServices.js +1 -1
- package/lib/commonjs/core/index.js +84 -2
- package/lib/commonjs/core/index.js.map +1 -1
- package/lib/commonjs/index.js +22 -22
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/node/index.js +6 -6
- package/lib/commonjs/node/index.js.map +1 -1
- package/lib/commonjs/ui/components/Avatar.js +3 -3
- package/lib/commonjs/ui/components/Avatar.js.map +1 -1
- package/lib/commonjs/ui/components/FollowButton.js +3 -3
- package/lib/commonjs/ui/components/GroupedSection.js +1 -1
- package/lib/commonjs/ui/components/OxyLogo.js +1 -1
- package/lib/commonjs/ui/components/OxyProvider.js +13 -13
- package/lib/commonjs/ui/components/OxyProvider.js.map +1 -1
- package/lib/commonjs/ui/components/OxySignInButton.js +2 -2
- package/lib/commonjs/ui/components/ProfileCard.js +2 -2
- package/lib/commonjs/ui/components/Section.js +1 -1
- package/lib/commonjs/ui/components/SectionTitle.js +1 -1
- package/lib/commonjs/ui/components/icon/index.js +1 -1
- package/lib/commonjs/ui/components/index.js +12 -12
- package/lib/commonjs/ui/context/OxyContext.js +20 -4
- package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
- package/lib/commonjs/ui/index.js +11 -11
- package/lib/commonjs/ui/index.js.map +1 -1
- package/lib/commonjs/ui/navigation/OxyRouter.js +18 -18
- package/lib/commonjs/ui/screens/AccountCenterScreen.js +18 -18
- package/lib/commonjs/ui/screens/AccountCenterScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountManagementDemo.js +3 -3
- package/lib/commonjs/ui/screens/AccountManagementDemo.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountOverviewScreen.js +45 -27
- package/lib/commonjs/ui/screens/AccountOverviewScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountSettingsScreen.js +29 -22
- package/lib/commonjs/ui/screens/AccountSettingsScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountSwitcherScreen.js +3 -3
- package/lib/commonjs/ui/screens/AppInfoScreen.js +6 -6
- package/lib/commonjs/ui/screens/BillingManagementScreen.js +3 -3
- package/lib/commonjs/ui/screens/FileManagementScreen.js +324 -306
- package/lib/commonjs/ui/screens/FileManagementScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/PremiumSubscriptionScreen.js +3 -3
- package/lib/commonjs/ui/screens/ProfileScreen.js +2 -2
- package/lib/commonjs/ui/screens/SessionManagementScreen.js +2 -2
- package/lib/commonjs/ui/screens/SignInScreen.js +358 -310
- package/lib/commonjs/ui/screens/SignInScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/SignUpScreen.js +483 -308
- package/lib/commonjs/ui/screens/SignUpScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/karma/KarmaCenterScreen.js +3 -3
- package/lib/commonjs/ui/screens/karma/KarmaFAQScreen.js +51 -26
- package/lib/commonjs/ui/screens/karma/KarmaFAQScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/karma/KarmaLeaderboardScreen.js +2 -2
- package/lib/commonjs/ui/screens/karma/KarmaRulesScreen.js +1 -1
- package/lib/commonjs/ui/styles/index.js +2 -2
- package/lib/commonjs/ui/styles/theme.js +1 -1
- package/lib/commonjs/utils/index.js +1 -1
- package/lib/module/assets/icons/OxyServices.js +1 -1
- package/lib/module/assets/icons/OxyServices.js.map +1 -1
- package/lib/module/core/index.js +84 -2
- package/lib/module/core/index.js.map +1 -1
- package/lib/module/index.js +10 -10
- package/lib/module/index.js.map +1 -1
- package/lib/module/node/index.js +4 -4
- package/lib/module/node/index.js.map +1 -1
- package/lib/module/ui/components/Avatar.js +2 -2
- package/lib/module/ui/components/Avatar.js.map +1 -1
- package/lib/module/ui/components/FollowButton.js +3 -3
- package/lib/module/ui/components/FollowButton.js.map +1 -1
- package/lib/module/ui/components/GroupedSection.js +1 -1
- package/lib/module/ui/components/GroupedSection.js.map +1 -1
- package/lib/module/ui/components/OxyLogo.js +1 -1
- package/lib/module/ui/components/OxyLogo.js.map +1 -1
- package/lib/module/ui/components/OxyProvider.js +10 -10
- package/lib/module/ui/components/OxyProvider.js.map +1 -1
- package/lib/module/ui/components/OxySignInButton.js +2 -2
- package/lib/module/ui/components/OxySignInButton.js.map +1 -1
- package/lib/module/ui/components/ProfileCard.js +2 -2
- package/lib/module/ui/components/ProfileCard.js.map +1 -1
- package/lib/module/ui/components/Section.js +1 -1
- package/lib/module/ui/components/Section.js.map +1 -1
- package/lib/module/ui/components/SectionTitle.js +1 -1
- package/lib/module/ui/components/SectionTitle.js.map +1 -1
- package/lib/module/ui/components/icon/index.js +1 -1
- package/lib/module/ui/components/icon/index.js.map +1 -1
- package/lib/module/ui/components/index.js +12 -12
- package/lib/module/ui/components/index.js.map +1 -1
- package/lib/module/ui/context/OxyContext.js +20 -4
- package/lib/module/ui/context/OxyContext.js.map +1 -1
- package/lib/module/ui/index.js +10 -10
- package/lib/module/ui/index.js.map +1 -1
- package/lib/module/ui/navigation/OxyRouter.js +18 -18
- package/lib/module/ui/navigation/OxyRouter.js.map +1 -1
- package/lib/module/ui/screens/AccountCenterScreen.js +5 -5
- package/lib/module/ui/screens/AccountCenterScreen.js.map +1 -1
- package/lib/module/ui/screens/AccountManagementDemo.js +2 -2
- package/lib/module/ui/screens/AccountManagementDemo.js.map +1 -1
- package/lib/module/ui/screens/AccountOverviewScreen.js +46 -28
- package/lib/module/ui/screens/AccountOverviewScreen.js.map +1 -1
- package/lib/module/ui/screens/AccountSettingsScreen.js +30 -23
- package/lib/module/ui/screens/AccountSettingsScreen.js.map +1 -1
- package/lib/module/ui/screens/AccountSwitcherScreen.js +3 -3
- package/lib/module/ui/screens/AccountSwitcherScreen.js.map +1 -1
- package/lib/module/ui/screens/AppInfoScreen.js +6 -6
- package/lib/module/ui/screens/AppInfoScreen.js.map +1 -1
- package/lib/module/ui/screens/BillingManagementScreen.js +3 -3
- package/lib/module/ui/screens/BillingManagementScreen.js.map +1 -1
- package/lib/module/ui/screens/FileManagementScreen.js +325 -307
- package/lib/module/ui/screens/FileManagementScreen.js.map +1 -1
- package/lib/module/ui/screens/PremiumSubscriptionScreen.js +3 -3
- package/lib/module/ui/screens/PremiumSubscriptionScreen.js.map +1 -1
- package/lib/module/ui/screens/ProfileScreen.js +2 -2
- package/lib/module/ui/screens/ProfileScreen.js.map +1 -1
- package/lib/module/ui/screens/SessionManagementScreen.js +2 -2
- package/lib/module/ui/screens/SessionManagementScreen.js.map +1 -1
- package/lib/module/ui/screens/SignInScreen.js +358 -310
- package/lib/module/ui/screens/SignInScreen.js.map +1 -1
- package/lib/module/ui/screens/SignUpScreen.js +486 -309
- package/lib/module/ui/screens/SignUpScreen.js.map +1 -1
- package/lib/module/ui/screens/karma/KarmaCenterScreen.js +3 -3
- package/lib/module/ui/screens/karma/KarmaCenterScreen.js.map +1 -1
- package/lib/module/ui/screens/karma/KarmaFAQScreen.js +52 -27
- package/lib/module/ui/screens/karma/KarmaFAQScreen.js.map +1 -1
- package/lib/module/ui/screens/karma/KarmaLeaderboardScreen.js +2 -2
- package/lib/module/ui/screens/karma/KarmaLeaderboardScreen.js.map +1 -1
- package/lib/module/ui/screens/karma/KarmaRulesScreen.js +1 -1
- package/lib/module/ui/screens/karma/KarmaRulesScreen.js.map +1 -1
- package/lib/module/ui/styles/index.js +2 -2
- package/lib/module/ui/styles/index.js.map +1 -1
- package/lib/module/ui/styles/theme.js +1 -1
- package/lib/module/ui/styles/theme.js.map +1 -1
- package/lib/module/utils/index.js +1 -1
- package/lib/module/utils/index.js.map +1 -1
- package/lib/typescript/core/index.d.ts +24 -0
- package/lib/typescript/core/index.d.ts.map +1 -1
- package/lib/typescript/ui/components/OxyProvider.d.ts.map +1 -1
- package/lib/typescript/ui/context/OxyContext.d.ts.map +1 -1
- package/lib/typescript/ui/screens/AccountOverviewScreen.d.ts +2 -2
- package/lib/typescript/ui/screens/AccountOverviewScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/AccountSettingsScreen.d.ts +2 -2
- package/lib/typescript/ui/screens/AccountSettingsScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/FileManagementScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/SignInScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/SignUpScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/karma/KarmaFAQScreen.d.ts +2 -2
- package/lib/typescript/ui/screens/karma/KarmaFAQScreen.d.ts.map +1 -1
- package/package.json +21 -5
- package/src/core/index.ts +68 -0
- package/src/ui/components/OxyProvider.tsx +5 -5
- package/src/ui/context/OxyContext.tsx +61 -41
- package/src/ui/screens/AccountOverviewScreen.tsx +44 -26
- package/src/ui/screens/AccountSettingsScreen.tsx +24 -18
- package/src/ui/screens/FileManagementScreen.tsx +246 -211
- package/src/ui/screens/SignInScreen.tsx +382 -326
- package/src/ui/screens/SignUpScreen.tsx +443 -273
- package/src/ui/screens/karma/KarmaFAQScreen.tsx +50 -29
- package/lib/commonjs/package.json +0 -1
- package/lib/module/package.json +0 -1
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
import React, { useState, useRef, useEffect } from 'react';
|
|
4
|
-
import { View, Text, TextInput, TouchableOpacity, StyleSheet, ActivityIndicator, Platform, Animated } from 'react-native';
|
|
5
|
-
import { useOxy } from
|
|
6
|
-
import { useThemeColors, createCommonStyles } from
|
|
7
|
-
import
|
|
8
|
-
import Avatar from '../components/Avatar';
|
|
9
|
-
import { BottomSheetScrollView } from '../components/bottomSheet';
|
|
3
|
+
import React, { useState, useRef, useEffect, useMemo, useCallback } from 'react';
|
|
4
|
+
import { View, Text, TextInput, TouchableOpacity, StyleSheet, ActivityIndicator, Platform, KeyboardAvoidingView, ScrollView, Animated, StatusBar } from 'react-native';
|
|
5
|
+
import { useOxy } from "../context/OxyContext.js";
|
|
6
|
+
import { useThemeColors, createCommonStyles } from "../styles/index.js";
|
|
7
|
+
import Avatar from "../components/Avatar.js";
|
|
10
8
|
import { Ionicons } from '@expo/vector-icons';
|
|
11
9
|
import Svg, { Path, Circle, Defs, LinearGradient, Stop } from 'react-native-svg';
|
|
12
|
-
import { toast } from
|
|
10
|
+
import { toast } from "../../lib/sonner.js";
|
|
13
11
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
14
12
|
const SignInScreen = ({
|
|
15
13
|
navigate,
|
|
@@ -21,10 +19,16 @@ const SignInScreen = ({
|
|
|
21
19
|
const [password, setPassword] = useState('');
|
|
22
20
|
const [errorMessage, setErrorMessage] = useState('');
|
|
23
21
|
const [userProfile, setUserProfile] = useState(null);
|
|
22
|
+
const [showPassword, setShowPassword] = useState(false);
|
|
24
23
|
|
|
25
24
|
// Multi-step form states
|
|
26
25
|
const [currentStep, setCurrentStep] = useState(0);
|
|
27
26
|
const [isInputFocused, setIsInputFocused] = useState(false);
|
|
27
|
+
const [isValidating, setIsValidating] = useState(false);
|
|
28
|
+
const [validationStatus, setValidationStatus] = useState('idle');
|
|
29
|
+
|
|
30
|
+
// Cache for validation results to prevent repeated API calls
|
|
31
|
+
const validationCache = useRef(new Map());
|
|
28
32
|
const fadeAnim = useRef(new Animated.Value(1)).current;
|
|
29
33
|
const slideAnim = useRef(new Animated.Value(0)).current;
|
|
30
34
|
const scaleAnim = useRef(new Animated.Value(1)).current;
|
|
@@ -36,13 +40,17 @@ const SignInScreen = ({
|
|
|
36
40
|
isLoading,
|
|
37
41
|
user,
|
|
38
42
|
isAuthenticated,
|
|
39
|
-
sessions
|
|
43
|
+
sessions,
|
|
44
|
+
oxyServices
|
|
40
45
|
} = useOxy();
|
|
41
46
|
const colors = useThemeColors(theme);
|
|
42
47
|
const commonStyles = createCommonStyles(theme);
|
|
43
48
|
|
|
44
49
|
// Check if this should be treated as "Add Account" mode
|
|
45
|
-
const isAddAccountMode = user && isAuthenticated && sessions && sessions.length > 0;
|
|
50
|
+
const isAddAccountMode = useMemo(() => user && isAuthenticated && sessions && sessions.length > 0, [user, isAuthenticated, sessions]);
|
|
51
|
+
|
|
52
|
+
// Memoized styles to prevent rerenders
|
|
53
|
+
const styles = useMemo(() => createStyles(colors, theme), [colors, theme]);
|
|
46
54
|
|
|
47
55
|
// Initialize logo animation
|
|
48
56
|
useEffect(() => {
|
|
@@ -52,26 +60,153 @@ const SignInScreen = ({
|
|
|
52
60
|
friction: 8,
|
|
53
61
|
useNativeDriver: true
|
|
54
62
|
}).start();
|
|
55
|
-
}, []);
|
|
63
|
+
}, [logoAnim]);
|
|
56
64
|
|
|
57
65
|
// Input focus animations
|
|
58
|
-
const handleInputFocus = () => {
|
|
66
|
+
const handleInputFocus = useCallback(() => {
|
|
59
67
|
setIsInputFocused(true);
|
|
60
68
|
Animated.spring(inputScaleAnim, {
|
|
61
69
|
toValue: 1.02,
|
|
62
70
|
useNativeDriver: true
|
|
63
71
|
}).start();
|
|
64
|
-
};
|
|
65
|
-
const handleInputBlur = () => {
|
|
72
|
+
}, [inputScaleAnim]);
|
|
73
|
+
const handleInputBlur = useCallback(() => {
|
|
66
74
|
setIsInputFocused(false);
|
|
67
75
|
Animated.spring(inputScaleAnim, {
|
|
68
76
|
toValue: 1,
|
|
69
77
|
useNativeDriver: true
|
|
70
78
|
}).start();
|
|
71
|
-
};
|
|
79
|
+
}, [inputScaleAnim]);
|
|
80
|
+
|
|
81
|
+
// Memoized input change handlers to prevent re-renders
|
|
82
|
+
const handleUsernameChange = useCallback(text => {
|
|
83
|
+
setUsername(text);
|
|
84
|
+
// Only clear error if we're changing from an invalid state
|
|
85
|
+
if (validationStatus === 'invalid') {
|
|
86
|
+
setErrorMessage('');
|
|
87
|
+
setValidationStatus('idle');
|
|
88
|
+
}
|
|
89
|
+
}, [validationStatus]);
|
|
90
|
+
const handlePasswordChange = useCallback(text => {
|
|
91
|
+
setPassword(text);
|
|
92
|
+
setErrorMessage(''); // Clear error when user types
|
|
93
|
+
}, []);
|
|
94
|
+
|
|
95
|
+
// Username validation using core services with caching
|
|
96
|
+
const validateUsername = useCallback(async usernameToValidate => {
|
|
97
|
+
if (!usernameToValidate || usernameToValidate.length < 3) {
|
|
98
|
+
setValidationStatus('invalid');
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Check cache first (cache valid for 5 minutes)
|
|
103
|
+
const cached = validationCache.current.get(usernameToValidate);
|
|
104
|
+
const now = Date.now();
|
|
105
|
+
if (cached && now - cached.timestamp < 5 * 60 * 1000) {
|
|
106
|
+
setUserProfile(cached.profile);
|
|
107
|
+
setValidationStatus('valid');
|
|
108
|
+
setErrorMessage('');
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
setIsValidating(true);
|
|
112
|
+
setValidationStatus('validating');
|
|
113
|
+
try {
|
|
114
|
+
// First check if username exists by trying to get profile
|
|
115
|
+
const profile = await oxyServices.getUserProfileByUsername(usernameToValidate);
|
|
116
|
+
if (profile) {
|
|
117
|
+
const profileData = {
|
|
118
|
+
displayName: profile.name?.full || profile.name?.first || profile.username,
|
|
119
|
+
name: profile.username,
|
|
120
|
+
avatar: profile.avatar,
|
|
121
|
+
id: profile.id
|
|
122
|
+
};
|
|
123
|
+
setUserProfile(profileData);
|
|
124
|
+
setValidationStatus('valid');
|
|
125
|
+
setErrorMessage(''); // Clear any previous errors
|
|
126
|
+
|
|
127
|
+
// Cache the result
|
|
128
|
+
validationCache.current.set(usernameToValidate, {
|
|
129
|
+
profile: profileData,
|
|
130
|
+
timestamp: now
|
|
131
|
+
});
|
|
132
|
+
return true;
|
|
133
|
+
} else {
|
|
134
|
+
setValidationStatus('invalid');
|
|
135
|
+
setErrorMessage('Username not found. Please check your username or sign up.');
|
|
136
|
+
return false;
|
|
137
|
+
}
|
|
138
|
+
} catch (error) {
|
|
139
|
+
// If user not found (404), username doesn't exist
|
|
140
|
+
if (error.status === 404 || error.code === 'USER_NOT_FOUND') {
|
|
141
|
+
setValidationStatus('invalid');
|
|
142
|
+
setErrorMessage('Username not found. Please check your username or sign up.');
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// For other errors, show generic message
|
|
147
|
+
console.error('Username validation error:', error);
|
|
148
|
+
setValidationStatus('invalid');
|
|
149
|
+
setErrorMessage('Unable to validate username. Please try again.');
|
|
150
|
+
return false;
|
|
151
|
+
} finally {
|
|
152
|
+
setIsValidating(false);
|
|
153
|
+
}
|
|
154
|
+
}, [oxyServices]);
|
|
155
|
+
|
|
156
|
+
// Debounced username validation - increased debounce time and added better conditions
|
|
157
|
+
useEffect(() => {
|
|
158
|
+
if (!username || username.length < 3) {
|
|
159
|
+
setValidationStatus('idle');
|
|
160
|
+
setUserProfile(null);
|
|
161
|
+
setErrorMessage(''); // Clear error when input is too short
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Only validate if we haven't already validated this exact username
|
|
166
|
+
if (validationStatus === 'valid' && userProfile?.name === username) {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
const timeoutId = setTimeout(() => {
|
|
170
|
+
validateUsername(username);
|
|
171
|
+
}, 800); // Increased debounce to 800ms
|
|
172
|
+
|
|
173
|
+
return () => clearTimeout(timeoutId);
|
|
174
|
+
}, [username, validateUsername, validationStatus, userProfile?.name]);
|
|
175
|
+
|
|
176
|
+
// Cleanup cache on unmount and limit cache size
|
|
177
|
+
useEffect(() => {
|
|
178
|
+
return () => {
|
|
179
|
+
// Clear cache on unmount
|
|
180
|
+
validationCache.current.clear();
|
|
181
|
+
};
|
|
182
|
+
}, []);
|
|
183
|
+
|
|
184
|
+
// Clean up old cache entries periodically (older than 10 minutes)
|
|
185
|
+
useEffect(() => {
|
|
186
|
+
const cleanupInterval = setInterval(() => {
|
|
187
|
+
const now = Date.now();
|
|
188
|
+
const maxAge = 10 * 60 * 1000; // 10 minutes
|
|
189
|
+
|
|
190
|
+
for (const [key, value] of validationCache.current.entries()) {
|
|
191
|
+
if (now - value.timestamp > maxAge) {
|
|
192
|
+
validationCache.current.delete(key);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Limit cache size to 50 entries
|
|
197
|
+
if (validationCache.current.size > 50) {
|
|
198
|
+
const entries = Array.from(validationCache.current.entries());
|
|
199
|
+
entries.sort((a, b) => a[1].timestamp - b[1].timestamp);
|
|
200
|
+
const toDelete = entries.slice(0, entries.length - 50);
|
|
201
|
+
toDelete.forEach(([key]) => validationCache.current.delete(key));
|
|
202
|
+
}
|
|
203
|
+
}, 5 * 60 * 1000); // Clean up every 5 minutes
|
|
204
|
+
|
|
205
|
+
return () => clearInterval(cleanupInterval);
|
|
206
|
+
}, []);
|
|
72
207
|
|
|
73
208
|
// Animation functions
|
|
74
|
-
const animateTransition = nextStep => {
|
|
209
|
+
const animateTransition = useCallback(nextStep => {
|
|
75
210
|
// Scale down current content
|
|
76
211
|
Animated.timing(scaleAnim, {
|
|
77
212
|
toValue: 0.95,
|
|
@@ -108,8 +243,8 @@ const SignInScreen = ({
|
|
|
108
243
|
useNativeDriver: true
|
|
109
244
|
})]).start();
|
|
110
245
|
});
|
|
111
|
-
};
|
|
112
|
-
const nextStep = () => {
|
|
246
|
+
}, [fadeAnim, slideAnim, scaleAnim]);
|
|
247
|
+
const nextStep = useCallback(() => {
|
|
113
248
|
if (currentStep < 1) {
|
|
114
249
|
// Animate progress bar
|
|
115
250
|
Animated.timing(progressAnim, {
|
|
@@ -119,8 +254,8 @@ const SignInScreen = ({
|
|
|
119
254
|
}).start();
|
|
120
255
|
animateTransition(currentStep + 1);
|
|
121
256
|
}
|
|
122
|
-
};
|
|
123
|
-
const prevStep = () => {
|
|
257
|
+
}, [currentStep, progressAnim, animateTransition]);
|
|
258
|
+
const prevStep = useCallback(() => {
|
|
124
259
|
if (currentStep > 0) {
|
|
125
260
|
// Animate progress bar
|
|
126
261
|
Animated.timing(progressAnim, {
|
|
@@ -130,37 +265,31 @@ const SignInScreen = ({
|
|
|
130
265
|
}).start();
|
|
131
266
|
animateTransition(currentStep - 1);
|
|
132
267
|
}
|
|
133
|
-
};
|
|
134
|
-
|
|
135
|
-
// Fetch user profile when username is entered
|
|
136
|
-
useEffect(() => {
|
|
137
|
-
const fetchUserProfile = async () => {
|
|
138
|
-
if (username.length >= 3 && currentStep === 1) {
|
|
139
|
-
try {
|
|
140
|
-
// For now, we'll create a mock profile based on username
|
|
141
|
-
// In a real app, you'd fetch this from your API
|
|
142
|
-
setUserProfile({
|
|
143
|
-
displayName: username,
|
|
144
|
-
name: username,
|
|
145
|
-
avatar: null // Could be fetched from API
|
|
146
|
-
});
|
|
147
|
-
} catch (error) {
|
|
148
|
-
// If user not found, we'll show a generic avatar
|
|
149
|
-
setUserProfile(null);
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
};
|
|
153
|
-
fetchUserProfile();
|
|
154
|
-
}, [username, currentStep]);
|
|
155
|
-
const handleUsernameNext = () => {
|
|
268
|
+
}, [currentStep, progressAnim, animateTransition]);
|
|
269
|
+
const handleUsernameNext = useCallback(() => {
|
|
156
270
|
if (!username) {
|
|
157
271
|
toast.error('Please enter your username');
|
|
158
272
|
return;
|
|
159
273
|
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
274
|
+
if (validationStatus === 'invalid') {
|
|
275
|
+
// Don't show toast if we already have an error message displayed
|
|
276
|
+
if (!errorMessage) {
|
|
277
|
+
toast.error('Please enter a valid username');
|
|
278
|
+
}
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
if (validationStatus === 'validating') {
|
|
282
|
+
toast.error('Please wait while we validate your username');
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
if (validationStatus === 'valid' && userProfile) {
|
|
286
|
+
setErrorMessage('');
|
|
287
|
+
nextStep();
|
|
288
|
+
} else {
|
|
289
|
+
toast.error('Please enter a valid username');
|
|
290
|
+
}
|
|
291
|
+
}, [username, validationStatus, userProfile, errorMessage, nextStep]);
|
|
292
|
+
const handleLogin = useCallback(async () => {
|
|
164
293
|
if (!username || !password) {
|
|
165
294
|
toast.error('Please enter both username and password');
|
|
166
295
|
return;
|
|
@@ -172,10 +301,10 @@ const SignInScreen = ({
|
|
|
172
301
|
} catch (error) {
|
|
173
302
|
toast.error(error.message || 'Login failed');
|
|
174
303
|
}
|
|
175
|
-
};
|
|
304
|
+
}, [username, password, login]);
|
|
176
305
|
|
|
177
|
-
//
|
|
178
|
-
const renderUsernameStep = () => /*#__PURE__*/_jsxs(Animated.View, {
|
|
306
|
+
// Memoized step components
|
|
307
|
+
const renderUsernameStep = useMemo(() => /*#__PURE__*/_jsxs(Animated.View, {
|
|
179
308
|
style: [styles.stepContainer, {
|
|
180
309
|
opacity: fadeAnim,
|
|
181
310
|
transform: [{
|
|
@@ -326,15 +455,15 @@ const SignInScreen = ({
|
|
|
326
455
|
}],
|
|
327
456
|
children: errorMessage
|
|
328
457
|
})]
|
|
329
|
-
}) : null, /*#__PURE__*/
|
|
458
|
+
}) : null, /*#__PURE__*/_jsxs(Animated.View, {
|
|
330
459
|
style: [styles.modernInputContainer, {
|
|
331
460
|
transform: [{
|
|
332
461
|
scale: inputScaleAnim
|
|
333
462
|
}]
|
|
334
463
|
}],
|
|
335
|
-
children: /*#__PURE__*/_jsxs(View, {
|
|
464
|
+
children: [/*#__PURE__*/_jsxs(View, {
|
|
336
465
|
style: [styles.inputWrapper, {
|
|
337
|
-
borderColor: isInputFocused ? colors.primary : colors.border
|
|
466
|
+
borderColor: validationStatus === 'valid' ? colors.success : validationStatus === 'invalid' ? colors.error : isInputFocused ? colors.primary : colors.border
|
|
338
467
|
}],
|
|
339
468
|
children: [/*#__PURE__*/_jsx(Ionicons, {
|
|
340
469
|
name: "person-outline",
|
|
@@ -348,31 +477,78 @@ const SignInScreen = ({
|
|
|
348
477
|
placeholder: "Enter your username",
|
|
349
478
|
placeholderTextColor: colors.placeholder,
|
|
350
479
|
value: username,
|
|
351
|
-
onChangeText:
|
|
480
|
+
onChangeText: handleUsernameChange,
|
|
352
481
|
onFocus: handleInputFocus,
|
|
353
482
|
onBlur: handleInputBlur,
|
|
354
483
|
autoCapitalize: "none",
|
|
355
484
|
testID: "username-input"
|
|
485
|
+
}), validationStatus === 'validating' && /*#__PURE__*/_jsx(ActivityIndicator, {
|
|
486
|
+
size: "small",
|
|
487
|
+
color: colors.primary,
|
|
488
|
+
style: styles.validationIndicator
|
|
489
|
+
}), validationStatus === 'valid' && /*#__PURE__*/_jsx(Ionicons, {
|
|
490
|
+
name: "checkmark-circle",
|
|
491
|
+
size: 20,
|
|
492
|
+
color: colors.success,
|
|
493
|
+
style: styles.validationIndicator
|
|
494
|
+
}), validationStatus === 'invalid' && username.length >= 3 && /*#__PURE__*/_jsx(Ionicons, {
|
|
495
|
+
name: "close-circle",
|
|
496
|
+
size: 20,
|
|
497
|
+
color: colors.error,
|
|
498
|
+
style: styles.validationIndicator
|
|
356
499
|
})]
|
|
357
|
-
})
|
|
358
|
-
|
|
500
|
+
}), validationStatus === 'valid' && userProfile && /*#__PURE__*/_jsxs(View, {
|
|
501
|
+
style: [styles.validationSuccessCard, {
|
|
502
|
+
backgroundColor: colors.success + '15'
|
|
503
|
+
}],
|
|
504
|
+
children: [/*#__PURE__*/_jsx(Ionicons, {
|
|
505
|
+
name: "checkmark-circle",
|
|
506
|
+
size: 16,
|
|
507
|
+
color: colors.success
|
|
508
|
+
}), /*#__PURE__*/_jsxs(Text, {
|
|
509
|
+
style: [styles.validationText, {
|
|
510
|
+
color: colors.success
|
|
511
|
+
}],
|
|
512
|
+
children: ["Found user: ", userProfile.displayName]
|
|
513
|
+
})]
|
|
514
|
+
}), validationStatus === 'invalid' && username.length >= 3 && !errorMessage && /*#__PURE__*/_jsxs(View, {
|
|
515
|
+
style: [styles.validationErrorCard, {
|
|
516
|
+
backgroundColor: colors.error + '15'
|
|
517
|
+
}],
|
|
518
|
+
children: [/*#__PURE__*/_jsx(Ionicons, {
|
|
519
|
+
name: "alert-circle",
|
|
520
|
+
size: 16,
|
|
521
|
+
color: colors.error
|
|
522
|
+
}), /*#__PURE__*/_jsx(Text, {
|
|
523
|
+
style: [styles.validationText, {
|
|
524
|
+
color: colors.error
|
|
525
|
+
}],
|
|
526
|
+
children: "Username not found"
|
|
527
|
+
})]
|
|
528
|
+
})]
|
|
529
|
+
}), /*#__PURE__*/_jsx(TouchableOpacity, {
|
|
359
530
|
style: [styles.modernButton, {
|
|
360
531
|
backgroundColor: colors.primary,
|
|
361
|
-
opacity: !username ? 0.5 : 1,
|
|
532
|
+
opacity: !username || validationStatus !== 'valid' ? 0.5 : 1,
|
|
362
533
|
shadowColor: colors.primary
|
|
363
534
|
}],
|
|
364
535
|
onPress: handleUsernameNext,
|
|
365
|
-
disabled: !username,
|
|
536
|
+
disabled: !username || validationStatus !== 'valid' || isValidating,
|
|
366
537
|
testID: "username-next-button",
|
|
367
|
-
children:
|
|
368
|
-
style: styles.modernButtonText,
|
|
369
|
-
children: "Continue"
|
|
370
|
-
}), /*#__PURE__*/_jsx(Ionicons, {
|
|
371
|
-
name: "arrow-forward",
|
|
372
|
-
size: 20,
|
|
538
|
+
children: isValidating ? /*#__PURE__*/_jsx(ActivityIndicator, {
|
|
373
539
|
color: "#FFFFFF",
|
|
374
|
-
|
|
375
|
-
})
|
|
540
|
+
size: "small"
|
|
541
|
+
}) : /*#__PURE__*/_jsxs(_Fragment, {
|
|
542
|
+
children: [/*#__PURE__*/_jsx(Text, {
|
|
543
|
+
style: styles.modernButtonText,
|
|
544
|
+
children: "Continue"
|
|
545
|
+
}), /*#__PURE__*/_jsx(Ionicons, {
|
|
546
|
+
name: "arrow-forward",
|
|
547
|
+
size: 20,
|
|
548
|
+
color: "#FFFFFF",
|
|
549
|
+
style: styles.buttonIcon
|
|
550
|
+
})]
|
|
551
|
+
})
|
|
376
552
|
}), /*#__PURE__*/_jsxs(View, {
|
|
377
553
|
style: styles.footerTextContainer,
|
|
378
554
|
children: [/*#__PURE__*/_jsxs(Text, {
|
|
@@ -390,8 +566,8 @@ const SignInScreen = ({
|
|
|
390
566
|
})
|
|
391
567
|
})]
|
|
392
568
|
})]
|
|
393
|
-
});
|
|
394
|
-
const renderPasswordStep = () => /*#__PURE__*/_jsxs(Animated.View, {
|
|
569
|
+
}), [fadeAnim, slideAnim, scaleAnim, colors, isAddAccountMode, user?.username, errorMessage, inputScaleAnim, isInputFocused, username, validationStatus, userProfile, isValidating, handleInputFocus, handleInputBlur, handleUsernameChange, handleUsernameNext, navigate, styles]);
|
|
570
|
+
const renderPasswordStep = useMemo(() => /*#__PURE__*/_jsxs(Animated.View, {
|
|
395
571
|
style: [styles.stepContainer, {
|
|
396
572
|
opacity: fadeAnim,
|
|
397
573
|
transform: [{
|
|
@@ -480,21 +656,30 @@ const SignInScreen = ({
|
|
|
480
656
|
placeholder: "Enter your password",
|
|
481
657
|
placeholderTextColor: colors.placeholder,
|
|
482
658
|
value: password,
|
|
483
|
-
onChangeText:
|
|
659
|
+
onChangeText: handlePasswordChange,
|
|
484
660
|
onFocus: handleInputFocus,
|
|
485
661
|
onBlur: handleInputBlur,
|
|
486
|
-
secureTextEntry:
|
|
662
|
+
secureTextEntry: !showPassword,
|
|
663
|
+
autoCapitalize: "none",
|
|
487
664
|
testID: "password-input"
|
|
665
|
+
}), /*#__PURE__*/_jsx(TouchableOpacity, {
|
|
666
|
+
style: styles.passwordToggle,
|
|
667
|
+
onPress: () => setShowPassword(!showPassword),
|
|
668
|
+
children: /*#__PURE__*/_jsx(Ionicons, {
|
|
669
|
+
name: showPassword ? "eye-off" : "eye",
|
|
670
|
+
size: 20,
|
|
671
|
+
color: colors.secondaryText
|
|
672
|
+
})
|
|
488
673
|
})]
|
|
489
674
|
})
|
|
490
675
|
}), /*#__PURE__*/_jsx(TouchableOpacity, {
|
|
491
676
|
style: [styles.modernButton, {
|
|
492
677
|
backgroundColor: colors.primary,
|
|
493
|
-
opacity:
|
|
678
|
+
opacity: !password ? 0.5 : 1,
|
|
494
679
|
shadowColor: colors.primary
|
|
495
680
|
}],
|
|
496
681
|
onPress: handleLogin,
|
|
497
|
-
disabled: isLoading,
|
|
682
|
+
disabled: !password || isLoading,
|
|
498
683
|
testID: "login-button",
|
|
499
684
|
children: isLoading ? /*#__PURE__*/_jsx(ActivityIndicator, {
|
|
500
685
|
color: "#FFFFFF",
|
|
@@ -502,9 +687,9 @@ const SignInScreen = ({
|
|
|
502
687
|
}) : /*#__PURE__*/_jsxs(_Fragment, {
|
|
503
688
|
children: [/*#__PURE__*/_jsx(Text, {
|
|
504
689
|
style: styles.modernButtonText,
|
|
505
|
-
children:
|
|
690
|
+
children: "Sign In"
|
|
506
691
|
}), /*#__PURE__*/_jsx(Ionicons, {
|
|
507
|
-
name: "
|
|
692
|
+
name: "log-in",
|
|
508
693
|
size: 20,
|
|
509
694
|
color: "#FFFFFF",
|
|
510
695
|
style: styles.buttonIcon
|
|
@@ -518,8 +703,8 @@ const SignInScreen = ({
|
|
|
518
703
|
}],
|
|
519
704
|
onPress: prevStep,
|
|
520
705
|
children: [/*#__PURE__*/_jsx(Ionicons, {
|
|
521
|
-
name: "
|
|
522
|
-
size:
|
|
706
|
+
name: "arrow-back",
|
|
707
|
+
size: 18,
|
|
523
708
|
color: colors.text
|
|
524
709
|
}), /*#__PURE__*/_jsx(Text, {
|
|
525
710
|
style: [styles.modernBackButtonText, {
|
|
@@ -532,216 +717,123 @@ const SignInScreen = ({
|
|
|
532
717
|
style: styles.securityNotice,
|
|
533
718
|
children: [/*#__PURE__*/_jsx(Ionicons, {
|
|
534
719
|
name: "shield-checkmark",
|
|
535
|
-
size:
|
|
720
|
+
size: 14,
|
|
536
721
|
color: colors.secondaryText
|
|
537
722
|
}), /*#__PURE__*/_jsx(Text, {
|
|
538
723
|
style: [styles.securityText, {
|
|
539
724
|
color: colors.secondaryText
|
|
540
725
|
}],
|
|
541
|
-
children: "Your
|
|
726
|
+
children: "Your data is encrypted and secure"
|
|
542
727
|
})]
|
|
543
728
|
})]
|
|
544
|
-
});
|
|
545
|
-
const renderCurrentStep = () => {
|
|
729
|
+
}), [fadeAnim, slideAnim, scaleAnim, colors, userProfile, username, theme, logoAnim, errorMessage, inputScaleAnim, isInputFocused, password, showPassword, handleInputFocus, handleInputBlur, handlePasswordChange, handleLogin, isLoading, prevStep, styles]);
|
|
730
|
+
const renderCurrentStep = useCallback(() => {
|
|
546
731
|
switch (currentStep) {
|
|
547
732
|
case 0:
|
|
548
|
-
return renderUsernameStep
|
|
733
|
+
return renderUsernameStep;
|
|
549
734
|
case 1:
|
|
550
|
-
return renderPasswordStep
|
|
735
|
+
return renderPasswordStep;
|
|
551
736
|
default:
|
|
552
|
-
return renderUsernameStep
|
|
737
|
+
return renderUsernameStep;
|
|
553
738
|
}
|
|
554
|
-
};
|
|
555
|
-
return /*#__PURE__*/_jsxs(
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
height: 50
|
|
570
|
-
})
|
|
571
|
-
}), /*#__PURE__*/_jsxs(View, {
|
|
572
|
-
style: styles.modernProgressContainer,
|
|
573
|
-
children: [/*#__PURE__*/_jsx(View, {
|
|
574
|
-
style: styles.progressTrack,
|
|
575
|
-
children: /*#__PURE__*/_jsx(Animated.View, {
|
|
576
|
-
style: [styles.progressFill, {
|
|
577
|
-
backgroundColor: colors.primary,
|
|
578
|
-
width: progressAnim.interpolate({
|
|
579
|
-
inputRange: [0, 1],
|
|
580
|
-
outputRange: ['50%', '100%']
|
|
581
|
-
})
|
|
582
|
-
}]
|
|
583
|
-
})
|
|
584
|
-
}), /*#__PURE__*/_jsxs(Text, {
|
|
585
|
-
style: [styles.progressText, {
|
|
586
|
-
color: colors.secondaryText
|
|
587
|
-
}],
|
|
588
|
-
children: ["Step ", currentStep + 1, " of 2"]
|
|
589
|
-
})]
|
|
590
|
-
}), renderCurrentStep()]
|
|
739
|
+
}, [currentStep, renderUsernameStep, renderPasswordStep]);
|
|
740
|
+
return /*#__PURE__*/_jsxs(KeyboardAvoidingView, {
|
|
741
|
+
style: [styles.container, {
|
|
742
|
+
backgroundColor: colors.background
|
|
743
|
+
}],
|
|
744
|
+
behavior: Platform.OS === 'ios' ? 'padding' : 'height',
|
|
745
|
+
children: [/*#__PURE__*/_jsx(StatusBar, {
|
|
746
|
+
barStyle: theme === 'dark' ? 'light-content' : 'dark-content',
|
|
747
|
+
backgroundColor: colors.background
|
|
748
|
+
}), /*#__PURE__*/_jsx(ScrollView, {
|
|
749
|
+
contentContainerStyle: styles.scrollContent,
|
|
750
|
+
showsVerticalScrollIndicator: false,
|
|
751
|
+
keyboardShouldPersistTaps: "handled",
|
|
752
|
+
children: renderCurrentStep()
|
|
753
|
+
})]
|
|
591
754
|
});
|
|
592
755
|
};
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
fontSize: 54,
|
|
599
|
-
marginBottom: 24
|
|
600
|
-
},
|
|
601
|
-
formContainer: {
|
|
602
|
-
width: '100%'
|
|
603
|
-
},
|
|
604
|
-
inputContainer: {
|
|
605
|
-
marginBottom: 16
|
|
756
|
+
|
|
757
|
+
// Memoized styles creation
|
|
758
|
+
const createStyles = (colors, theme) => StyleSheet.create({
|
|
759
|
+
container: {
|
|
760
|
+
flex: 1
|
|
606
761
|
},
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
762
|
+
scrollContent: {
|
|
763
|
+
flexGrow: 1,
|
|
764
|
+
paddingHorizontal: 24,
|
|
765
|
+
paddingTop: 40,
|
|
766
|
+
paddingBottom: 40
|
|
611
767
|
},
|
|
612
|
-
|
|
613
|
-
|
|
768
|
+
stepContainer: {
|
|
769
|
+
flex: 1,
|
|
614
770
|
justifyContent: 'center',
|
|
615
|
-
marginTop: 24
|
|
616
|
-
},
|
|
617
|
-
footerText: {
|
|
618
|
-
fontSize: 14,
|
|
619
|
-
lineHeight: 20
|
|
620
|
-
},
|
|
621
|
-
linkText: {
|
|
622
|
-
fontSize: 14,
|
|
623
|
-
lineHeight: 20,
|
|
624
|
-
fontWeight: '600'
|
|
625
|
-
},
|
|
626
|
-
userInfoContainer: {
|
|
627
|
-
padding: 20,
|
|
628
|
-
marginVertical: 20,
|
|
629
|
-
borderRadius: 35,
|
|
630
|
-
alignItems: 'center'
|
|
631
|
-
},
|
|
632
|
-
userInfoText: {
|
|
633
|
-
fontSize: 16,
|
|
634
|
-
lineHeight: 24,
|
|
635
|
-
textAlign: 'center'
|
|
636
|
-
},
|
|
637
|
-
actionButtonsContainer: {
|
|
638
|
-
marginTop: 20
|
|
639
|
-
},
|
|
640
|
-
infoContainer: {
|
|
641
|
-
padding: 16,
|
|
642
|
-
marginVertical: 16,
|
|
643
|
-
borderRadius: 8,
|
|
644
|
-
alignItems: 'center'
|
|
645
|
-
},
|
|
646
|
-
infoText: {
|
|
647
|
-
fontSize: 14,
|
|
648
|
-
lineHeight: 20,
|
|
649
|
-
textAlign: 'center'
|
|
650
|
-
},
|
|
651
|
-
// Modern UI Styles
|
|
652
|
-
logoContainer: {
|
|
653
|
-
alignItems: 'center',
|
|
654
|
-
marginBottom: 16
|
|
655
|
-
},
|
|
656
|
-
modernProgressContainer: {
|
|
657
771
|
alignItems: 'center',
|
|
658
|
-
|
|
659
|
-
paddingHorizontal: 20
|
|
660
|
-
},
|
|
661
|
-
progressTrack: {
|
|
662
|
-
width: '100%',
|
|
663
|
-
height: 4,
|
|
664
|
-
backgroundColor: '#E5E5E5',
|
|
665
|
-
borderRadius: 2,
|
|
666
|
-
marginBottom: 8,
|
|
667
|
-
overflow: 'hidden'
|
|
668
|
-
},
|
|
669
|
-
progressFill: {
|
|
670
|
-
height: '100%',
|
|
671
|
-
borderRadius: 2
|
|
772
|
+
minHeight: 600
|
|
672
773
|
},
|
|
673
|
-
progressText: {
|
|
674
|
-
fontSize: 12,
|
|
675
|
-
fontWeight: '500'
|
|
676
|
-
},
|
|
677
|
-
stepContainer: {
|
|
678
|
-
width: '100%',
|
|
679
|
-
minHeight: 450,
|
|
680
|
-
paddingHorizontal: 20
|
|
681
|
-
},
|
|
682
|
-
// Modern Image Container
|
|
683
774
|
modernImageContainer: {
|
|
684
775
|
alignItems: 'center',
|
|
685
|
-
marginBottom: 40
|
|
686
|
-
paddingVertical: 20
|
|
776
|
+
marginBottom: 40
|
|
687
777
|
},
|
|
688
778
|
modernHeader: {
|
|
689
|
-
alignItems: '
|
|
690
|
-
|
|
779
|
+
alignItems: 'flex-start',
|
|
780
|
+
width: '100%',
|
|
781
|
+
marginBottom: 32
|
|
691
782
|
},
|
|
692
783
|
modernTitle: {
|
|
693
784
|
fontFamily: Platform.OS === 'web' ? 'Phudu' : 'Phudu-Bold',
|
|
694
785
|
fontWeight: Platform.OS === 'web' ? 'bold' : undefined,
|
|
695
|
-
fontSize:
|
|
696
|
-
|
|
697
|
-
marginBottom:
|
|
698
|
-
|
|
786
|
+
fontSize: 42,
|
|
787
|
+
lineHeight: 48,
|
|
788
|
+
marginBottom: 12,
|
|
789
|
+
textAlign: 'left',
|
|
790
|
+
letterSpacing: -1
|
|
699
791
|
},
|
|
700
792
|
modernSubtitle: {
|
|
701
|
-
fontSize:
|
|
702
|
-
lineHeight:
|
|
703
|
-
textAlign: '
|
|
793
|
+
fontSize: 18,
|
|
794
|
+
lineHeight: 24,
|
|
795
|
+
textAlign: 'left',
|
|
704
796
|
opacity: 0.8
|
|
705
797
|
},
|
|
706
|
-
// Modern Cards
|
|
707
798
|
modernInfoCard: {
|
|
708
799
|
flexDirection: 'row',
|
|
709
800
|
alignItems: 'center',
|
|
710
801
|
padding: 16,
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
gap: 12
|
|
802
|
+
borderRadius: 16,
|
|
803
|
+
marginBottom: 24,
|
|
804
|
+
gap: 12,
|
|
805
|
+
width: '100%'
|
|
714
806
|
},
|
|
715
807
|
modernInfoText: {
|
|
716
808
|
fontSize: 14,
|
|
717
|
-
lineHeight: 20,
|
|
718
809
|
flex: 1
|
|
719
810
|
},
|
|
720
811
|
modernErrorCard: {
|
|
721
812
|
flexDirection: 'row',
|
|
722
813
|
alignItems: 'center',
|
|
723
814
|
padding: 16,
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
gap: 12
|
|
815
|
+
borderRadius: 16,
|
|
816
|
+
marginBottom: 24,
|
|
817
|
+
gap: 12,
|
|
818
|
+
width: '100%'
|
|
727
819
|
},
|
|
728
820
|
errorText: {
|
|
729
821
|
fontSize: 14,
|
|
730
|
-
|
|
822
|
+
fontWeight: '500',
|
|
731
823
|
flex: 1
|
|
732
824
|
},
|
|
733
|
-
// Modern Input Styles
|
|
734
825
|
modernInputContainer: {
|
|
826
|
+
width: '100%',
|
|
735
827
|
marginBottom: 24
|
|
736
828
|
},
|
|
737
829
|
inputWrapper: {
|
|
738
830
|
flexDirection: 'row',
|
|
739
831
|
alignItems: 'center',
|
|
740
|
-
|
|
832
|
+
height: 56,
|
|
741
833
|
borderRadius: 16,
|
|
742
|
-
paddingHorizontal:
|
|
743
|
-
|
|
744
|
-
backgroundColor:
|
|
834
|
+
paddingHorizontal: 20,
|
|
835
|
+
borderWidth: 2,
|
|
836
|
+
backgroundColor: colors.inputBackground
|
|
745
837
|
},
|
|
746
838
|
inputIcon: {
|
|
747
839
|
marginRight: 12
|
|
@@ -749,10 +841,34 @@ const styles = StyleSheet.create({
|
|
|
749
841
|
modernInput: {
|
|
750
842
|
flex: 1,
|
|
751
843
|
fontSize: 16,
|
|
752
|
-
|
|
844
|
+
height: '100%'
|
|
845
|
+
},
|
|
846
|
+
passwordToggle: {
|
|
847
|
+
padding: 4
|
|
848
|
+
},
|
|
849
|
+
validationIndicator: {
|
|
850
|
+
marginLeft: 8
|
|
851
|
+
},
|
|
852
|
+
validationSuccessCard: {
|
|
853
|
+
flexDirection: 'row',
|
|
854
|
+
alignItems: 'center',
|
|
855
|
+
padding: 12,
|
|
856
|
+
borderRadius: 12,
|
|
857
|
+
marginTop: 8,
|
|
858
|
+
gap: 8
|
|
859
|
+
},
|
|
860
|
+
validationErrorCard: {
|
|
861
|
+
flexDirection: 'row',
|
|
862
|
+
alignItems: 'center',
|
|
863
|
+
padding: 12,
|
|
864
|
+
borderRadius: 12,
|
|
865
|
+
marginTop: 8,
|
|
866
|
+
gap: 8
|
|
867
|
+
},
|
|
868
|
+
validationText: {
|
|
869
|
+
fontSize: 12,
|
|
753
870
|
fontWeight: '500'
|
|
754
871
|
},
|
|
755
|
-
// Modern Button Styles
|
|
756
872
|
modernButton: {
|
|
757
873
|
flexDirection: 'row',
|
|
758
874
|
alignItems: 'center',
|
|
@@ -768,7 +884,8 @@ const styles = StyleSheet.create({
|
|
|
768
884
|
shadowOpacity: 0.3,
|
|
769
885
|
shadowRadius: 8,
|
|
770
886
|
elevation: 6,
|
|
771
|
-
gap: 8
|
|
887
|
+
gap: 8,
|
|
888
|
+
width: '100%'
|
|
772
889
|
},
|
|
773
890
|
modernButtonText: {
|
|
774
891
|
color: '#FFFFFF',
|
|
@@ -785,6 +902,14 @@ const styles = StyleSheet.create({
|
|
|
785
902
|
fontWeight: '600',
|
|
786
903
|
textDecorationLine: 'underline'
|
|
787
904
|
},
|
|
905
|
+
footerTextContainer: {
|
|
906
|
+
flexDirection: 'row',
|
|
907
|
+
justifyContent: 'center',
|
|
908
|
+
marginTop: 28
|
|
909
|
+
},
|
|
910
|
+
footerText: {
|
|
911
|
+
fontSize: 15
|
|
912
|
+
},
|
|
788
913
|
// Modern User Profile Styles
|
|
789
914
|
modernUserProfileContainer: {
|
|
790
915
|
alignItems: 'center',
|
|
@@ -867,83 +992,6 @@ const styles = StyleSheet.create({
|
|
|
867
992
|
securityText: {
|
|
868
993
|
fontSize: 12,
|
|
869
994
|
fontWeight: '500'
|
|
870
|
-
},
|
|
871
|
-
// Legacy compatibility styles
|
|
872
|
-
progressContainer: {
|
|
873
|
-
flexDirection: 'row',
|
|
874
|
-
alignItems: 'center',
|
|
875
|
-
justifyContent: 'center',
|
|
876
|
-
marginBottom: 32,
|
|
877
|
-
paddingHorizontal: 40
|
|
878
|
-
},
|
|
879
|
-
progressDot: {
|
|
880
|
-
width: 12,
|
|
881
|
-
height: 12,
|
|
882
|
-
borderRadius: 6,
|
|
883
|
-
marginHorizontal: 4
|
|
884
|
-
},
|
|
885
|
-
progressLine: {
|
|
886
|
-
flex: 1,
|
|
887
|
-
height: 2,
|
|
888
|
-
marginHorizontal: 8
|
|
889
|
-
},
|
|
890
|
-
welcomeImageContainer: {
|
|
891
|
-
alignItems: 'center',
|
|
892
|
-
marginBottom: 32
|
|
893
|
-
},
|
|
894
|
-
header: {
|
|
895
|
-
alignItems: 'center',
|
|
896
|
-
marginBottom: 16
|
|
897
|
-
},
|
|
898
|
-
welcomeTitle: {
|
|
899
|
-
fontFamily: Platform.OS === 'web' ? 'Phudu' : 'Phudu-Bold',
|
|
900
|
-
fontWeight: Platform.OS === 'web' ? 'bold' : undefined,
|
|
901
|
-
fontSize: 32,
|
|
902
|
-
textAlign: 'center',
|
|
903
|
-
marginBottom: 8
|
|
904
|
-
},
|
|
905
|
-
welcomeText: {
|
|
906
|
-
fontSize: 16,
|
|
907
|
-
lineHeight: 24,
|
|
908
|
-
textAlign: 'center',
|
|
909
|
-
marginBottom: 32,
|
|
910
|
-
paddingHorizontal: 20
|
|
911
|
-
},
|
|
912
|
-
userProfileContainer: {
|
|
913
|
-
alignItems: 'center',
|
|
914
|
-
marginBottom: 32,
|
|
915
|
-
paddingVertical: 20
|
|
916
|
-
},
|
|
917
|
-
userAvatar: {
|
|
918
|
-
marginBottom: 16
|
|
919
|
-
},
|
|
920
|
-
userDisplayName: {
|
|
921
|
-
fontSize: 24,
|
|
922
|
-
fontWeight: 'bold',
|
|
923
|
-
marginBottom: 4,
|
|
924
|
-
textAlign: 'center'
|
|
925
|
-
},
|
|
926
|
-
usernameSubtext: {
|
|
927
|
-
fontSize: 16,
|
|
928
|
-
textAlign: 'center'
|
|
929
|
-
},
|
|
930
|
-
navigationButtons: {
|
|
931
|
-
flexDirection: 'row',
|
|
932
|
-
justifyContent: 'center',
|
|
933
|
-
marginTop: 24
|
|
934
|
-
},
|
|
935
|
-
backButton: {
|
|
936
|
-
flexDirection: 'row',
|
|
937
|
-
alignItems: 'center',
|
|
938
|
-
paddingVertical: 12,
|
|
939
|
-
paddingHorizontal: 20,
|
|
940
|
-
borderRadius: 12,
|
|
941
|
-
borderWidth: 1
|
|
942
|
-
},
|
|
943
|
-
backButtonText: {
|
|
944
|
-
fontSize: 16,
|
|
945
|
-
fontWeight: '500',
|
|
946
|
-
marginLeft: 8
|
|
947
995
|
}
|
|
948
996
|
});
|
|
949
997
|
export default SignInScreen;
|