feat: smooth navigation transitions + config updates
- Migrate MainStack from JS stack to native-stack for native-thread, jank-free screen transitions (slide_from_right, fade for auth screens) - Add shift animation to bottom tab switching - Install @react-navigation/native-stack - Update API URLs, Axios, Login and Android network security config Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
44e84ff6f1
commit
9acec328a7
@@ -1,5 +1,5 @@
|
||||
import React, { useState, useEffect, useCallback } from 'react';
|
||||
import { View, Text, StyleSheet, KeyboardAvoidingView, Platform, ScrollView, TouchableOpacity, Dimensions, StatusBar, TextInput, Image } from 'react-native';
|
||||
import { View, Text, StyleSheet, KeyboardAvoidingView, Platform, ScrollView, TouchableOpacity, Dimensions, StatusBar, TextInput, Image, ActivityIndicator, Keyboard } from 'react-native';
|
||||
import { Formik } from 'formik';
|
||||
import * as Yup from 'yup';
|
||||
import { useDispatch } from 'react-redux';
|
||||
@@ -43,7 +43,7 @@ const Login = () => {
|
||||
const [passwordVisible, setPasswordVisible] = useState(false);
|
||||
const [showForm, setShowForm] = useState(false);
|
||||
const [activeSlide, setActiveSlide] = useState(0);
|
||||
const { mutateAsync: registrationStateMutate } = useRagistrationState();
|
||||
const { mutateAsync: registrationStateMutate, isPending: isResolvingRoute } = useRagistrationState();
|
||||
|
||||
useEffect(() => {
|
||||
if (showForm) return;
|
||||
@@ -211,6 +211,9 @@ const Login = () => {
|
||||
const handleSuccess = (res: any) => {
|
||||
dispatch(setToken({ ...res.data, token: res.token, userType: 'tender' }));
|
||||
console.log('handleSuccess', res)
|
||||
console.log('==================== 🔑 AUTH TOKEN ====================');
|
||||
console.log('TOKEN →', res?.token);
|
||||
console.log('=======================================================');
|
||||
if (res.statusCode === 200) {
|
||||
handleGetData()
|
||||
} else {
|
||||
@@ -219,12 +222,18 @@ const Login = () => {
|
||||
};
|
||||
|
||||
const handleLogin = (values: any) => {
|
||||
if (isLoading) return; // guard against double submit
|
||||
Keyboard.dismiss(); // smooth the navigation transition (no keyboard mid-replace)
|
||||
const payload = { emailAdd: values.email, password: values.password, device: "mobileApp" };
|
||||
console.log('payload------------', payload)
|
||||
loginMutation.mutate(payload);
|
||||
};
|
||||
|
||||
const isLoading = loginMutation.isPending;
|
||||
// Covers the WHOLE sign-in flow: login request + registration-state resolve
|
||||
// (+ the brief moment before navigation.replace swaps the screen). Without
|
||||
// this, the button reverts to "SIGN IN" between the two requests, which is
|
||||
// the flicker/glitch the user sees.
|
||||
const isLoading = loginMutation.isPending || isResolvingRoute;
|
||||
|
||||
// Minimal Input Component (Enhanced for better aesthetics)
|
||||
const MinimalInput = ({ placeholder, value, onChangeText, onBlur, icon, secureTextEntry, rightIcon, onRightIconPress }: any) => {
|
||||
@@ -375,7 +384,7 @@ const Login = () => {
|
||||
|
||||
<View style={styles.cardInnerContent}>
|
||||
<View style={styles.formHeader}>
|
||||
<Text style={[styles.formTitle, { color: colors.text }]}>Welcome Back</Text>
|
||||
<Text style={[styles.formTitle, { color: colors.text }]}>Welcome</Text>
|
||||
<Text style={styles.formSubtitle}>Sign in to your account</Text>
|
||||
</View>
|
||||
<Formik
|
||||
@@ -413,18 +422,28 @@ const Login = () => {
|
||||
<TouchableOpacity
|
||||
activeOpacity={0.8}
|
||||
onPress={() => handleSubmit()}
|
||||
disabled={isLoading}
|
||||
style={styles.loginBtnContainer}
|
||||
>
|
||||
<LinearGradient
|
||||
colors={[colors.primary, '#f59953']}
|
||||
colors={isLoading ? ['#e8a44c99', '#f5995399'] : [colors.primary, '#f59953']}
|
||||
start={{ x: 0, y: 0 }}
|
||||
end={{ x: 1, y: 0 }}
|
||||
style={styles.loginBtn}
|
||||
>
|
||||
<Text style={styles.loginBtnText}>
|
||||
{isLoading ? 'Wait...' : 'SIGN IN'}
|
||||
</Text>
|
||||
{!isLoading && <ArrowRight size={22} color={'#FFF'} style={styles.arrowIcon} />}
|
||||
{isLoading ? (
|
||||
<>
|
||||
<ActivityIndicator size="small" color={'#FFF'} />
|
||||
<Text style={[styles.loginBtnText, styles.loginBtnTextLoading]}>
|
||||
SIGNING IN
|
||||
</Text>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Text style={styles.loginBtnText}>SIGN IN</Text>
|
||||
<ArrowRight size={22} color={'#FFF'} style={styles.arrowIcon} />
|
||||
</>
|
||||
)}
|
||||
</LinearGradient>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
@@ -445,6 +464,17 @@ const Login = () => {
|
||||
|
||||
</ScrollView>
|
||||
</KeyboardAvoidingView>
|
||||
|
||||
{/* Full-screen loader — covers the whole login→resolve→navigate flow so
|
||||
the user never sees a half-rendered state or the navigation flicker */}
|
||||
{isLoading && (
|
||||
<View style={styles.loaderOverlay} pointerEvents="auto">
|
||||
<View style={styles.loaderCard}>
|
||||
<ActivityIndicator size="large" color={colors.primary} />
|
||||
<Text style={[styles.loaderText, { color: colors.text }]}>Signing in…</Text>
|
||||
</View>
|
||||
</View>
|
||||
)}
|
||||
</AppBackground >
|
||||
);
|
||||
};
|
||||
@@ -688,10 +718,41 @@ const styles = StyleSheet.create({
|
||||
letterSpacing: 1.5,
|
||||
textTransform: 'uppercase',
|
||||
},
|
||||
loginBtnTextLoading: {
|
||||
marginLeft: 12,
|
||||
},
|
||||
arrowIcon: {
|
||||
marginLeft: 12,
|
||||
},
|
||||
|
||||
// FULL-SCREEN LOADER OVERLAY
|
||||
loaderOverlay: {
|
||||
...StyleSheet.absoluteFillObject,
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.35)',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
zIndex: 999,
|
||||
},
|
||||
loaderCard: {
|
||||
paddingVertical: 24,
|
||||
paddingHorizontal: 32,
|
||||
borderRadius: 20,
|
||||
backgroundColor: 'rgba(255, 255, 255, 0.95)',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
shadowColor: '#000',
|
||||
shadowOffset: { width: 0, height: 8 },
|
||||
shadowOpacity: 0.2,
|
||||
shadowRadius: 16,
|
||||
elevation: 10,
|
||||
},
|
||||
loaderText: {
|
||||
marginTop: 12,
|
||||
fontSize: 15,
|
||||
fontWeight: '600',
|
||||
fontFamily: FontsFamily.poppinsMedium,
|
||||
},
|
||||
|
||||
// FOOTER
|
||||
footer: {
|
||||
flexDirection: 'row',
|
||||
|
||||
Reference in New Issue
Block a user