@oxyhq/services 5.4.3 → 5.4.4
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/README.md +14 -0
- package/lib/commonjs/assets/assets/illustrations/HighFive.tsx +41 -0
- package/lib/commonjs/assets/icons/OxyServices.js +1 -1
- package/lib/commonjs/assets/illustrations/HighFive.js +61 -0
- package/lib/commonjs/assets/illustrations/HighFive.js.map +1 -0
- package/lib/commonjs/core/index.js +2 -2
- package/lib/commonjs/index.js +22 -22
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/node/createAuth.js +95 -0
- package/lib/commonjs/node/createAuth.js.map +1 -0
- package/lib/commonjs/node/index.js +15 -6
- package/lib/commonjs/node/index.js.map +1 -1
- package/lib/commonjs/package.json +1 -0
- 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 +146 -141
- 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/components/internal/GroupedPillButtons.js +213 -0
- package/lib/commonjs/ui/components/internal/GroupedPillButtons.js.map +1 -0
- package/lib/commonjs/ui/components/internal/TextField.js +576 -0
- package/lib/commonjs/ui/components/internal/TextField.js.map +1 -0
- package/lib/commonjs/ui/context/OxyContext.js +1 -1
- package/lib/commonjs/ui/index.js +19 -11
- package/lib/commonjs/ui/index.js.map +1 -1
- package/lib/commonjs/ui/navigation/OxyRouter.js +23 -18
- package/lib/commonjs/ui/navigation/OxyRouter.js.map +1 -1
- 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 +4 -4
- package/lib/commonjs/ui/screens/AccountSettingsScreen.js +5 -5
- 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/FeedbackScreen.js +1169 -0
- package/lib/commonjs/ui/screens/FeedbackScreen.js.map +1 -0
- package/lib/commonjs/ui/screens/FileManagementScreen.js +3 -3
- 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 +182 -304
- package/lib/commonjs/ui/screens/SignInScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/SignUpScreen.js +811 -712
- 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/KarmaLeaderboardScreen.js +2 -2
- package/lib/commonjs/ui/screens/karma/KarmaRulesScreen.js +1 -1
- package/lib/commonjs/ui/store/index.js +52 -0
- package/lib/commonjs/ui/store/index.js.map +1 -0
- 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/assets/illustrations/HighFive.tsx +41 -0
- package/lib/module/assets/icons/OxyServices.js +1 -1
- package/lib/module/assets/icons/OxyServices.js.map +1 -1
- package/lib/module/assets/illustrations/HighFive.js +55 -0
- package/lib/module/assets/illustrations/HighFive.js.map +1 -0
- package/lib/module/core/index.js +2 -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/createAuth.js +90 -0
- package/lib/module/node/createAuth.js.map +1 -0
- package/lib/module/node/index.js +8 -4
- package/lib/module/node/index.js.map +1 -1
- package/lib/module/package.json +1 -0
- 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 +143 -138
- 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/components/internal/GroupedPillButtons.js +208 -0
- package/lib/module/ui/components/internal/GroupedPillButtons.js.map +1 -0
- package/lib/module/ui/components/internal/TextField.js +571 -0
- package/lib/module/ui/components/internal/TextField.js.map +1 -0
- package/lib/module/ui/context/OxyContext.js +1 -1
- package/lib/module/ui/context/OxyContext.js.map +1 -1
- package/lib/module/ui/index.js +12 -10
- package/lib/module/ui/index.js.map +1 -1
- package/lib/module/ui/navigation/OxyRouter.js +23 -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 +4 -4
- package/lib/module/ui/screens/AccountOverviewScreen.js.map +1 -1
- package/lib/module/ui/screens/AccountSettingsScreen.js +5 -5
- 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/FeedbackScreen.js +1164 -0
- package/lib/module/ui/screens/FeedbackScreen.js.map +1 -0
- package/lib/module/ui/screens/FileManagementScreen.js +3 -3
- 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 +182 -304
- package/lib/module/ui/screens/SignInScreen.js.map +1 -1
- package/lib/module/ui/screens/SignUpScreen.js +810 -712
- 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/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/store/index.js +44 -0
- package/lib/module/ui/store/index.js.map +1 -0
- 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/assets/illustrations/HighFive.d.ts +9 -0
- package/lib/typescript/assets/illustrations/HighFive.d.ts.map +1 -0
- package/lib/typescript/node/createAuth.d.ts +7 -0
- package/lib/typescript/node/createAuth.d.ts.map +1 -0
- package/lib/typescript/node/index.d.ts +2 -0
- package/lib/typescript/node/index.d.ts.map +1 -1
- package/lib/typescript/types/expo-vector-icons.d.ts +3 -0
- package/lib/typescript/types/express.d.ts +5 -0
- package/lib/typescript/types/react-redux.d.ts +5 -0
- package/lib/typescript/ui/components/OxyProvider.d.ts.map +1 -1
- package/lib/typescript/ui/components/internal/GroupedPillButtons.d.ts +18 -0
- package/lib/typescript/ui/components/internal/GroupedPillButtons.d.ts.map +1 -0
- package/lib/typescript/ui/components/internal/TextField.d.ts +25 -0
- package/lib/typescript/ui/components/internal/TextField.d.ts.map +1 -0
- package/lib/typescript/ui/index.d.ts +2 -0
- package/lib/typescript/ui/index.d.ts.map +1 -1
- package/lib/typescript/ui/navigation/OxyRouter.d.ts.map +1 -1
- package/lib/typescript/ui/screens/FeedbackScreen.d.ts +5 -0
- package/lib/typescript/ui/screens/FeedbackScreen.d.ts.map +1 -0
- 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/store/index.d.ts +19 -0
- package/lib/typescript/ui/store/index.d.ts.map +1 -0
- package/package.json +10 -25
- package/src/assets/illustrations/HighFive.tsx +41 -0
- package/src/node/createAuth.ts +116 -0
- package/src/node/index.ts +4 -0
- package/src/types/expo-vector-icons.d.ts +3 -0
- package/src/types/express.d.ts +5 -0
- package/src/types/react-redux.d.ts +5 -0
- package/src/ui/components/OxyProvider.tsx +136 -135
- package/src/ui/components/internal/GroupedPillButtons.tsx +253 -0
- package/src/ui/components/internal/TextField.tsx +694 -0
- package/src/ui/index.ts +6 -2
- package/src/ui/navigation/OxyRouter.tsx +8 -3
- package/src/ui/screens/FeedbackScreen.tsx +1042 -0
- package/src/ui/screens/SignInScreen.tsx +179 -222
- package/src/ui/screens/SignUpScreen.tsx +772 -608
- package/src/ui/store/index.ts +51 -0
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
Animated,
|
|
14
14
|
Dimensions,
|
|
15
15
|
StatusBar,
|
|
16
|
+
Alert,
|
|
16
17
|
} from 'react-native';
|
|
17
18
|
import { BaseScreenProps } from '../navigation/types';
|
|
18
19
|
import { useOxy } from '../context/OxyContext';
|
|
@@ -21,12 +22,16 @@ import OxyLogo from '../components/OxyLogo';
|
|
|
21
22
|
import Avatar from '../components/Avatar';
|
|
22
23
|
import { BottomSheetScrollView } from '../components/bottomSheet';
|
|
23
24
|
import { Ionicons } from '@expo/vector-icons';
|
|
24
|
-
import
|
|
25
|
+
import HighFive from '../../assets/illustrations/HighFive';
|
|
25
26
|
import { toast } from '../../lib/sonner';
|
|
27
|
+
import Svg, { Path, Circle } from 'react-native-svg';
|
|
28
|
+
import GroupedPillButtons from '../components/internal/GroupedPillButtons';
|
|
29
|
+
import TextField from '../components/internal/TextField';
|
|
26
30
|
|
|
27
31
|
const SignInScreen: React.FC<BaseScreenProps> = ({
|
|
28
32
|
navigate,
|
|
29
33
|
goBack,
|
|
34
|
+
onAuthenticated,
|
|
30
35
|
theme,
|
|
31
36
|
}) => {
|
|
32
37
|
// Form data states
|
|
@@ -297,47 +302,39 @@ const SignInScreen: React.FC<BaseScreenProps> = ({
|
|
|
297
302
|
}
|
|
298
303
|
}, [currentStep, progressAnim, animateTransition]);
|
|
299
304
|
|
|
300
|
-
|
|
305
|
+
// Custom next handlers for validation
|
|
306
|
+
const handleUsernameContinue = useCallback(() => {
|
|
301
307
|
if (!username) {
|
|
302
|
-
toast.error('Please enter your username');
|
|
308
|
+
toast.error('Please enter your username.');
|
|
303
309
|
return;
|
|
304
310
|
}
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
// Don't show toast if we already have an error message displayed
|
|
308
|
-
if (!errorMessage) {
|
|
309
|
-
toast.error('Please enter a valid username');
|
|
310
|
-
}
|
|
311
|
+
if (validationStatus !== 'valid' || !userProfile) {
|
|
312
|
+
toast.error('Please enter a valid username.');
|
|
311
313
|
return;
|
|
312
314
|
}
|
|
315
|
+
setErrorMessage('');
|
|
316
|
+
nextStep();
|
|
317
|
+
}, [username, validationStatus, userProfile, setErrorMessage, nextStep]);
|
|
313
318
|
|
|
314
|
-
|
|
315
|
-
|
|
319
|
+
const handleSignIn = useCallback(async () => {
|
|
320
|
+
if (!password) {
|
|
321
|
+
toast.error('Please enter your password.');
|
|
316
322
|
return;
|
|
317
323
|
}
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
setErrorMessage('');
|
|
321
|
-
nextStep();
|
|
322
|
-
} else {
|
|
323
|
-
toast.error('Please enter a valid username');
|
|
324
|
-
}
|
|
325
|
-
}, [username, validationStatus, userProfile, errorMessage, nextStep]);
|
|
326
|
-
|
|
327
|
-
const handleLogin = useCallback(async () => {
|
|
328
|
-
if (!username || !password) {
|
|
329
|
-
toast.error('Please enter both username and password');
|
|
324
|
+
if (!username || !userProfile) {
|
|
325
|
+
toast.error('Please enter a valid username first.');
|
|
330
326
|
return;
|
|
331
327
|
}
|
|
332
|
-
|
|
333
328
|
try {
|
|
334
329
|
setErrorMessage('');
|
|
335
|
-
await login(username, password);
|
|
336
|
-
|
|
330
|
+
const user = await login(username, password);
|
|
331
|
+
if (onAuthenticated) {
|
|
332
|
+
onAuthenticated(user);
|
|
333
|
+
}
|
|
337
334
|
} catch (error: any) {
|
|
338
335
|
toast.error(error.message || 'Login failed');
|
|
339
336
|
}
|
|
340
|
-
}, [username, password, login]);
|
|
337
|
+
}, [username, password, login, onAuthenticated, setErrorMessage, userProfile]);
|
|
341
338
|
|
|
342
339
|
// Memoized step components
|
|
343
340
|
const renderUsernameStep = useMemo(() => (
|
|
@@ -351,52 +348,11 @@ const SignInScreen: React.FC<BaseScreenProps> = ({
|
|
|
351
348
|
]
|
|
352
349
|
}
|
|
353
350
|
]}>
|
|
354
|
-
<
|
|
355
|
-
<Svg width={280} height={160} viewBox="0 0 280 160">
|
|
356
|
-
<Defs>
|
|
357
|
-
<LinearGradient id="primaryGradient" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
358
|
-
<Stop offset="0%" stopColor={colors.primary} stopOpacity="0.8" />
|
|
359
|
-
<Stop offset="100%" stopColor={colors.primary} stopOpacity="0.2" />
|
|
360
|
-
</LinearGradient>
|
|
361
|
-
<LinearGradient id="secondaryGradient" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
362
|
-
<Stop offset="0%" stopColor={colors.primary} stopOpacity="0.1" />
|
|
363
|
-
<Stop offset="100%" stopColor={colors.primary} stopOpacity="0.3" />
|
|
364
|
-
</LinearGradient>
|
|
365
|
-
</Defs>
|
|
366
|
-
|
|
367
|
-
{/* Modern abstract shapes */}
|
|
368
|
-
<Circle cx="80" cy="80" r="45" fill="url(#primaryGradient)" />
|
|
369
|
-
<Circle cx="200" cy="80" r="35" fill="url(#secondaryGradient)" />
|
|
370
|
-
<Path
|
|
371
|
-
d="M40 120 Q80 40 140 80 Q200 120 240 60"
|
|
372
|
-
stroke={colors.primary}
|
|
373
|
-
strokeWidth="4"
|
|
374
|
-
fill="none"
|
|
375
|
-
strokeLinecap="round"
|
|
376
|
-
/>
|
|
377
|
-
|
|
378
|
-
{/* Floating elements */}
|
|
379
|
-
<Circle cx="60" cy="50" r="8" fill={colors.primary} opacity="0.6" />
|
|
380
|
-
<Circle cx="220" cy="120" r="6" fill={colors.primary} opacity="0.4" />
|
|
381
|
-
<Circle cx="250" cy="40" r="4" fill={colors.primary} opacity="0.8" />
|
|
382
|
-
|
|
383
|
-
{/* Central focus element */}
|
|
384
|
-
<Circle cx="140" cy="80" r="25" fill={colors.background} opacity="0.9" />
|
|
385
|
-
<Circle cx="135" cy="75" r="3" fill={colors.primary} />
|
|
386
|
-
<Circle cx="145" cy="75" r="3" fill={colors.primary} />
|
|
387
|
-
<Path
|
|
388
|
-
d="M132 85 Q140 92 148 85"
|
|
389
|
-
stroke={colors.primary}
|
|
390
|
-
strokeWidth="2"
|
|
391
|
-
fill="none"
|
|
392
|
-
strokeLinecap="round"
|
|
393
|
-
/>
|
|
394
|
-
</Svg>
|
|
395
|
-
</View>
|
|
351
|
+
<HighFive width={100} height={100} />
|
|
396
352
|
|
|
397
353
|
<View style={styles.modernHeader}>
|
|
398
354
|
<Text style={[styles.modernTitle, { color: colors.text }]}>
|
|
399
|
-
{isAddAccountMode ? 'Add Account' : '
|
|
355
|
+
{isAddAccountMode ? 'Add Another Account' : 'Sign In'}
|
|
400
356
|
</Text>
|
|
401
357
|
<Text style={[styles.modernSubtitle, { color: colors.secondaryText }]}>
|
|
402
358
|
{isAddAccountMode
|
|
@@ -426,99 +382,124 @@ const SignInScreen: React.FC<BaseScreenProps> = ({
|
|
|
426
382
|
styles.modernInputContainer,
|
|
427
383
|
{ transform: [{ scale: inputScaleAnim }] }
|
|
428
384
|
]}>
|
|
429
|
-
<
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
placeholderTextColor={colors.placeholder}
|
|
447
|
-
value={username}
|
|
448
|
-
onChangeText={handleUsernameChange}
|
|
449
|
-
onFocus={handleInputFocus}
|
|
450
|
-
onBlur={handleInputBlur}
|
|
451
|
-
autoCapitalize="none"
|
|
452
|
-
testID="username-input"
|
|
453
|
-
/>
|
|
454
|
-
{validationStatus === 'validating' && (
|
|
455
|
-
<ActivityIndicator size="small" color={colors.primary} style={styles.validationIndicator} />
|
|
456
|
-
)}
|
|
457
|
-
{validationStatus === 'valid' && (
|
|
458
|
-
<Ionicons name="checkmark-circle" size={20} color={colors.success} style={styles.validationIndicator} />
|
|
459
|
-
)}
|
|
460
|
-
{validationStatus === 'invalid' && username.length >= 3 && (
|
|
461
|
-
<Ionicons name="close-circle" size={20} color={colors.error} style={styles.validationIndicator} />
|
|
462
|
-
)}
|
|
463
|
-
</View>
|
|
385
|
+
<TextField
|
|
386
|
+
label="Username"
|
|
387
|
+
icon="person-outline"
|
|
388
|
+
value={username}
|
|
389
|
+
onChangeText={handleUsernameChange}
|
|
390
|
+
onFocus={handleInputFocus}
|
|
391
|
+
onBlur={handleInputBlur}
|
|
392
|
+
autoCapitalize="none"
|
|
393
|
+
autoCorrect={false}
|
|
394
|
+
testID="username-input"
|
|
395
|
+
colors={colors}
|
|
396
|
+
variant="filled"
|
|
397
|
+
error={validationStatus === 'invalid' && username.length >= 3 ? 'Username not found' : undefined}
|
|
398
|
+
loading={validationStatus === 'validating'}
|
|
399
|
+
success={validationStatus === 'valid'}
|
|
400
|
+
/>
|
|
401
|
+
</Animated.View>
|
|
464
402
|
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
403
|
+
{/* Enhanced Validation feedback */}
|
|
404
|
+
{validationStatus === 'valid' && userProfile && (
|
|
405
|
+
<View style={[styles.validationSuccessCard, {
|
|
406
|
+
backgroundColor: colors.success + '10',
|
|
407
|
+
borderWidth: 1,
|
|
408
|
+
borderColor: colors.success + '30',
|
|
409
|
+
padding: 16,
|
|
410
|
+
}]}>
|
|
411
|
+
<View style={{
|
|
412
|
+
width: 32,
|
|
413
|
+
height: 32,
|
|
414
|
+
borderRadius: 16,
|
|
415
|
+
backgroundColor: colors.success + '20',
|
|
416
|
+
justifyContent: 'center',
|
|
417
|
+
alignItems: 'center',
|
|
418
|
+
marginRight: 12,
|
|
419
|
+
}}>
|
|
468
420
|
<Ionicons name="checkmark-circle" size={16} color={colors.success} />
|
|
469
|
-
|
|
470
|
-
|
|
421
|
+
</View>
|
|
422
|
+
<View style={{ flex: 1 }}>
|
|
423
|
+
<Text style={[styles.validationText, {
|
|
424
|
+
color: colors.success,
|
|
425
|
+
fontWeight: '600',
|
|
426
|
+
marginBottom: 2,
|
|
427
|
+
}]}>
|
|
428
|
+
Welcome back, {userProfile?.displayName || userProfile?.name || username}!
|
|
429
|
+
</Text>
|
|
430
|
+
<Text style={[styles.validationText, {
|
|
431
|
+
color: colors.secondaryText,
|
|
432
|
+
fontSize: 11,
|
|
433
|
+
opacity: 0.8,
|
|
434
|
+
}]}>
|
|
435
|
+
Ready to continue where you left off
|
|
471
436
|
</Text>
|
|
472
437
|
</View>
|
|
473
|
-
|
|
438
|
+
</View>
|
|
439
|
+
)}
|
|
474
440
|
|
|
475
|
-
|
|
476
|
-
|
|
441
|
+
{validationStatus === 'invalid' && username.length >= 3 && (
|
|
442
|
+
<View style={[styles.validationErrorCard, {
|
|
443
|
+
backgroundColor: colors.error + '10',
|
|
444
|
+
borderWidth: 1,
|
|
445
|
+
borderColor: colors.error + '30',
|
|
446
|
+
padding: 16,
|
|
447
|
+
}]}>
|
|
448
|
+
<View style={{
|
|
449
|
+
width: 32,
|
|
450
|
+
height: 32,
|
|
451
|
+
borderRadius: 16,
|
|
452
|
+
backgroundColor: colors.error + '20',
|
|
453
|
+
justifyContent: 'center',
|
|
454
|
+
alignItems: 'center',
|
|
455
|
+
marginRight: 12,
|
|
456
|
+
}}>
|
|
477
457
|
<Ionicons name="alert-circle" size={16} color={colors.error} />
|
|
478
|
-
|
|
458
|
+
</View>
|
|
459
|
+
<View style={{ flex: 1 }}>
|
|
460
|
+
<Text style={[styles.validationText, {
|
|
461
|
+
color: colors.error,
|
|
462
|
+
fontWeight: '600',
|
|
463
|
+
marginBottom: 2,
|
|
464
|
+
}]}>
|
|
479
465
|
Username not found
|
|
480
466
|
</Text>
|
|
467
|
+
<Text style={[styles.validationText, {
|
|
468
|
+
color: colors.secondaryText,
|
|
469
|
+
fontSize: 11,
|
|
470
|
+
opacity: 0.8,
|
|
471
|
+
}]}>
|
|
472
|
+
Check spelling or sign up
|
|
473
|
+
</Text>
|
|
481
474
|
</View>
|
|
482
|
-
|
|
483
|
-
|
|
475
|
+
</View>
|
|
476
|
+
)}
|
|
484
477
|
|
|
485
|
-
<
|
|
486
|
-
|
|
487
|
-
styles.modernButton,
|
|
478
|
+
<GroupedPillButtons
|
|
479
|
+
buttons={[
|
|
488
480
|
{
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
481
|
+
text: 'Sign Up',
|
|
482
|
+
onPress: () => navigate('SignUp'),
|
|
483
|
+
icon: 'person-add',
|
|
484
|
+
variant: 'transparent',
|
|
485
|
+
},
|
|
486
|
+
{
|
|
487
|
+
text: 'Continue',
|
|
488
|
+
onPress: handleUsernameContinue,
|
|
489
|
+
icon: 'arrow-forward',
|
|
490
|
+
variant: 'primary',
|
|
491
|
+
loading: isValidating,
|
|
492
|
+
testID: 'username-next-button',
|
|
493
|
+
},
|
|
493
494
|
]}
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
testID="username-next-button"
|
|
497
|
-
>
|
|
498
|
-
{isValidating ? (
|
|
499
|
-
<ActivityIndicator color="#FFFFFF" size="small" />
|
|
500
|
-
) : (
|
|
501
|
-
<>
|
|
502
|
-
<Text style={styles.modernButtonText}>Continue</Text>
|
|
503
|
-
<Ionicons name="arrow-forward" size={20} color="#FFFFFF" style={styles.buttonIcon} />
|
|
504
|
-
</>
|
|
505
|
-
)}
|
|
506
|
-
</TouchableOpacity>
|
|
507
|
-
|
|
508
|
-
<View style={styles.footerTextContainer}>
|
|
509
|
-
<Text style={[styles.footerText, { color: colors.secondaryText }]}>
|
|
510
|
-
Don't have an account?{' '}
|
|
511
|
-
</Text>
|
|
512
|
-
<TouchableOpacity onPress={() => navigate('SignUp')}>
|
|
513
|
-
<Text style={[styles.modernLinkText, { color: colors.primary }]}>Sign Up</Text>
|
|
514
|
-
</TouchableOpacity>
|
|
515
|
-
</View>
|
|
495
|
+
colors={colors}
|
|
496
|
+
/>
|
|
516
497
|
</Animated.View>
|
|
517
498
|
), [
|
|
518
499
|
fadeAnim, slideAnim, scaleAnim, colors, isAddAccountMode, user?.username,
|
|
519
500
|
errorMessage, inputScaleAnim, isInputFocused, username, validationStatus,
|
|
520
501
|
userProfile, isValidating, handleInputFocus, handleInputBlur, handleUsernameChange,
|
|
521
|
-
|
|
502
|
+
handleUsernameContinue, navigate, styles
|
|
522
503
|
]);
|
|
523
504
|
|
|
524
505
|
const renderPasswordStep = useMemo(() => (
|
|
@@ -573,70 +554,42 @@ const SignInScreen: React.FC<BaseScreenProps> = ({
|
|
|
573
554
|
styles.modernInputContainer,
|
|
574
555
|
{ transform: [{ scale: inputScaleAnim }] }
|
|
575
556
|
]}>
|
|
576
|
-
<
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
secureTextEntry={!showPassword}
|
|
592
|
-
autoCapitalize="none"
|
|
593
|
-
testID="password-input"
|
|
594
|
-
/>
|
|
595
|
-
<TouchableOpacity
|
|
596
|
-
style={styles.passwordToggle}
|
|
597
|
-
onPress={() => setShowPassword(!showPassword)}
|
|
598
|
-
>
|
|
599
|
-
<Ionicons
|
|
600
|
-
name={showPassword ? "eye-off" : "eye"}
|
|
601
|
-
size={20}
|
|
602
|
-
color={colors.secondaryText}
|
|
603
|
-
/>
|
|
604
|
-
</TouchableOpacity>
|
|
605
|
-
</View>
|
|
557
|
+
<TextField
|
|
558
|
+
label="Password"
|
|
559
|
+
icon="lock-closed-outline"
|
|
560
|
+
value={password}
|
|
561
|
+
onChangeText={handlePasswordChange}
|
|
562
|
+
onFocus={handleInputFocus}
|
|
563
|
+
onBlur={handleInputBlur}
|
|
564
|
+
secureTextEntry={!showPassword}
|
|
565
|
+
autoCapitalize="none"
|
|
566
|
+
autoCorrect={false}
|
|
567
|
+
testID="password-input"
|
|
568
|
+
colors={colors}
|
|
569
|
+
variant="filled"
|
|
570
|
+
error={errorMessage}
|
|
571
|
+
/>
|
|
606
572
|
</Animated.View>
|
|
607
573
|
|
|
608
|
-
<
|
|
609
|
-
|
|
610
|
-
styles.modernButton,
|
|
574
|
+
<GroupedPillButtons
|
|
575
|
+
buttons={[
|
|
611
576
|
{
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
577
|
+
text: 'Back',
|
|
578
|
+
onPress: prevStep,
|
|
579
|
+
icon: 'arrow-back',
|
|
580
|
+
variant: 'transparent',
|
|
581
|
+
},
|
|
582
|
+
{
|
|
583
|
+
text: 'Sign In',
|
|
584
|
+
onPress: handleSignIn,
|
|
585
|
+
icon: 'log-in',
|
|
586
|
+
variant: 'primary',
|
|
587
|
+
loading: isLoading,
|
|
588
|
+
testID: 'login-button',
|
|
589
|
+
},
|
|
616
590
|
]}
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
testID="login-button"
|
|
620
|
-
>
|
|
621
|
-
{isLoading ? (
|
|
622
|
-
<ActivityIndicator color="#FFFFFF" size="small" />
|
|
623
|
-
) : (
|
|
624
|
-
<>
|
|
625
|
-
<Text style={styles.modernButtonText}>Sign In</Text>
|
|
626
|
-
<Ionicons name="log-in" size={20} color="#FFFFFF" style={styles.buttonIcon} />
|
|
627
|
-
</>
|
|
628
|
-
)}
|
|
629
|
-
</TouchableOpacity>
|
|
630
|
-
|
|
631
|
-
<View style={styles.modernNavigationButtons}>
|
|
632
|
-
<TouchableOpacity
|
|
633
|
-
style={[styles.modernBackButton, { borderColor: colors.border }]}
|
|
634
|
-
onPress={prevStep}
|
|
635
|
-
>
|
|
636
|
-
<Ionicons name="arrow-back" size={18} color={colors.text} />
|
|
637
|
-
<Text style={[styles.modernBackButtonText, { color: colors.text }]}>Back</Text>
|
|
638
|
-
</TouchableOpacity>
|
|
639
|
-
</View>
|
|
591
|
+
colors={colors}
|
|
592
|
+
/>
|
|
640
593
|
|
|
641
594
|
<View style={styles.securityNotice}>
|
|
642
595
|
<Ionicons name="shield-checkmark" size={14} color={colors.secondaryText} />
|
|
@@ -648,7 +601,7 @@ const SignInScreen: React.FC<BaseScreenProps> = ({
|
|
|
648
601
|
), [
|
|
649
602
|
fadeAnim, slideAnim, scaleAnim, colors, userProfile, username, theme, logoAnim,
|
|
650
603
|
errorMessage, inputScaleAnim, isInputFocused, password, showPassword,
|
|
651
|
-
handleInputFocus, handleInputBlur, handlePasswordChange,
|
|
604
|
+
handleInputFocus, handleInputBlur, handlePasswordChange, handleSignIn, isLoading, prevStep, styles
|
|
652
605
|
]);
|
|
653
606
|
|
|
654
607
|
const renderCurrentStep = useCallback(() => {
|
|
@@ -691,30 +644,25 @@ const createStyles = (colors: any, theme: string) => StyleSheet.create({
|
|
|
691
644
|
scrollContent: {
|
|
692
645
|
flexGrow: 1,
|
|
693
646
|
paddingHorizontal: 24,
|
|
694
|
-
paddingTop:
|
|
695
|
-
paddingBottom:
|
|
647
|
+
paddingTop: 4,
|
|
648
|
+
paddingBottom: 20,
|
|
696
649
|
},
|
|
697
650
|
stepContainer: {
|
|
698
651
|
flex: 1,
|
|
699
|
-
justifyContent: '
|
|
700
|
-
alignItems: '
|
|
701
|
-
minHeight: 600,
|
|
702
|
-
},
|
|
703
|
-
modernImageContainer: {
|
|
704
|
-
alignItems: 'center',
|
|
705
|
-
marginBottom: 40,
|
|
652
|
+
justifyContent: 'flex-start',
|
|
653
|
+
alignItems: 'flex-start',
|
|
706
654
|
},
|
|
707
655
|
modernHeader: {
|
|
708
656
|
alignItems: 'flex-start',
|
|
709
657
|
width: '100%',
|
|
710
|
-
marginBottom:
|
|
658
|
+
marginBottom: 24,
|
|
711
659
|
},
|
|
712
660
|
modernTitle: {
|
|
713
661
|
fontFamily: Platform.OS === 'web' ? 'Phudu' : 'Phudu-Bold',
|
|
714
662
|
fontWeight: Platform.OS === 'web' ? 'bold' : undefined,
|
|
715
|
-
fontSize:
|
|
663
|
+
fontSize: 62,
|
|
716
664
|
lineHeight: 48,
|
|
717
|
-
marginBottom:
|
|
665
|
+
marginBottom: 18,
|
|
718
666
|
textAlign: 'left',
|
|
719
667
|
letterSpacing: -1,
|
|
720
668
|
},
|
|
@@ -825,6 +773,13 @@ const createStyles = (colors: any, theme: string) => StyleSheet.create({
|
|
|
825
773
|
buttonIcon: {
|
|
826
774
|
marginLeft: 4,
|
|
827
775
|
},
|
|
776
|
+
|
|
777
|
+
// Enhanced Label Styles
|
|
778
|
+
modernLabel: {
|
|
779
|
+
fontSize: 12,
|
|
780
|
+
fontWeight: '500',
|
|
781
|
+
marginBottom: 2,
|
|
782
|
+
},
|
|
828
783
|
modernLinkText: {
|
|
829
784
|
fontSize: 14,
|
|
830
785
|
lineHeight: 20,
|
|
@@ -834,7 +789,7 @@ const createStyles = (colors: any, theme: string) => StyleSheet.create({
|
|
|
834
789
|
footerTextContainer: {
|
|
835
790
|
flexDirection: 'row',
|
|
836
791
|
justifyContent: 'center',
|
|
837
|
-
marginTop:
|
|
792
|
+
marginTop: 16,
|
|
838
793
|
},
|
|
839
794
|
footerText: {
|
|
840
795
|
fontSize: 15,
|
|
@@ -896,8 +851,10 @@ const createStyles = (colors: any, theme: string) => StyleSheet.create({
|
|
|
896
851
|
modernNavigationButtons: {
|
|
897
852
|
flexDirection: 'row',
|
|
898
853
|
justifyContent: 'center',
|
|
899
|
-
marginTop:
|
|
900
|
-
marginBottom:
|
|
854
|
+
marginTop: 16,
|
|
855
|
+
marginBottom: 8,
|
|
856
|
+
width: '100%',
|
|
857
|
+
gap: 8,
|
|
901
858
|
},
|
|
902
859
|
modernBackButton: {
|
|
903
860
|
flexDirection: 'row',
|