2025-08-06 14:01:52 +08:00

194 lines
9.8 KiB
TypeScript

import Handers from '@/assets/icons/svg/handers.svg';
import ForgetPwd from '@/components/login/forgetPwd';
import Login from '@/components/login/login';
import PhoneLogin from '@/components/login/phoneLogin';
import SignUp from '@/components/login/signUp';
import PrivacyModal from '@/components/owner/qualification/privacy';
import { ThemedText } from '@/components/ThemedText';
import { ThemedView } from '@/components/ThemedView';
import { useLocalSearchParams, useRouter } from 'expo-router';
import React, { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { Image, Keyboard, KeyboardAvoidingView, LayoutChangeEvent, Platform, ScrollView, StatusBar, TouchableOpacity, View, ViewStyle, useWindowDimensions } from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
const LoginScreen = () => {
const router = useRouter();
const { t } = useTranslation();
const { status } = useLocalSearchParams();
const [error, setError] = useState<string>('123');
const [containerHeight, setContainerHeight] = useState(0);
const { height: windowHeight } = useWindowDimensions();
// 展示首次输入密码
const [showPassword, setShowPassword] = useState(false);
// 展示二次输入密码
const [showSecondPassword, setShowSecondPassword] = useState(false);
const [keyboardOffset, setKeyboardOffset] = useState(0);
const insets = useSafeAreaInsets();
// 判断是否有白边
const statusBarHeight = StatusBar?.currentHeight ?? 0;
// 协议弹窗
const [modalVisible, setModalVisible] = useState(false);
const [modalType, setModalType] = useState<'ai' | 'terms' | 'privacy' | 'user' | 'membership'>('privacy');
useEffect(() => {
const keyboardWillShowListener = Keyboard.addListener(
Platform.OS === 'ios' ? 'keyboardWillShow' : 'keyboardDidShow',
(e) => {
setKeyboardOffset(e.endCoordinates.height);
}
);
const keyboardWillHideListener = Keyboard.addListener(
Platform.OS === 'ios' ? 'keyboardWillHide' : 'keyboardDidHide',
() => {
setKeyboardOffset(0);
}
);
return () => {
keyboardWillShowListener.remove();
keyboardWillHideListener.remove();
};
}, []);
const handleLayout = (event: LayoutChangeEvent) => {
const { height } = event.nativeEvent.layout;
setContainerHeight(height);
};
const updateUrlParam = (key: string, value: string) => {
setError('');
router.setParams({ [key]: value });
}
return (
<KeyboardAvoidingView
style={{ flex: 1 }}
behavior={Platform.OS === "ios" ? "padding" : "height"}
keyboardVerticalOffset={Platform.OS === 'ios' ? 0 : -statusBarHeight}
>
<ScrollView
contentContainerStyle={{
flexGrow: 1
}}
keyboardShouldPersistTaps="handled"
bounces={false}
>
<ThemedView className="flex-1 bg-bgPrimary justify-end">
<View style={{ width: "100%", alignItems: "center", marginTop: insets.top + 8 }}>
<ThemedText style={{ fontSize: 20, fontWeight: 'bold', color: "#fff" }}>Awake your Memo</ThemedText>
</View>
<View className="flex-1">
<View
className="absolute left-1/2 z-10"
style={{
top: containerHeight > 0 ? windowHeight - containerHeight - 210 + statusBarHeight - insets.top - 28 : 0,
transform: [{ translateX: -200 }, { translateY: keyboardOffset > 0 ? -keyboardOffset + statusBarHeight - insets.top - 28 : -keyboardOffset }]
}}
>
{
(showPassword || showSecondPassword)
?
<Image source={require('@/assets/images/png/icon/ipNoHandsEyes.png')} />
:
<Image source={require('@/assets/images/png/icon/ipNoHands.png')} />
}
</View>
<View
className="absolute left-1/2 z-[1000] -translate-x-[39.5px] -translate-y-[4px]"
style={{
top: containerHeight > 0 ? windowHeight - containerHeight - 1 + statusBarHeight - insets.top - 30 : 0,
transform: [{ translateX: -39.5 }, { translateY: keyboardOffset > 0 ? -4 - keyboardOffset + statusBarHeight - insets.top - 30 : -4 - keyboardOffset }]
}}
>
<Handers />
</View>
</View>
<ThemedView
className="w-full bg-white pt-4 px-6 relative z-20 shadow-lg pb-5"
style={{
borderTopLeftRadius: 50,
borderTopRightRadius: 50,
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.1,
shadowRadius: 8,
elevation: 5,
paddingBottom: insets.bottom
} as ViewStyle}
onLayout={handleLayout}
>
{/* 错误提示 */}
<View className={`${error !== "123" ? 'opacity-100' : 'opacity-0'} w-full flex justify-center items-center text-primary-500 text-sm`}>
<ThemedText className="text-sm !text-textPrimary">
{error}
</ThemedText>
</View>
{(() => {
const commonProps = {
updateUrlParam,
setError,
};
const components = {
signUp: (
<SignUp
{...commonProps}
setShowPassword={setShowPassword}
showPassword={showPassword}
setShowSecondPassword={setShowSecondPassword}
showSecondPassword={showSecondPassword}
/>
),
forgetPwd: (
<ForgetPwd
{...commonProps}
/>
),
login: (
<Login
{...commonProps}
setShowPassword={setShowPassword}
showPassword={showPassword}
/>
// <PhoneLogin {...commonProps} />
),
code: (
<PhoneLogin {...commonProps} />
)
};
return components[status as keyof typeof components] || components.login;
})()}
<View style={{ width: "100%", alignItems: "center", marginTop: 16 }}>
{status == 'login' || !status &&
<View className="flex-row justify-center mt-2 flex-wrap w-[85%] items-center">
<ThemedText style={{ fontSize: 11, color: "#FFB645" }}>
{status === 'login' || !status ? t('auth.agree.logintext', { ns: 'login' }) : t('auth.agree.singupText', { ns: 'login' })}
</ThemedText>
<TouchableOpacity onPress={() => { setModalVisible(true); setModalType('terms') }}>
<ThemedText style={{ fontSize: 11, color: "#FFB645", textDecorationLine: 'underline' }}>
{t('auth.agree.terms', { ns: 'login' })}
</ThemedText>
</TouchableOpacity>
<ThemedText style={{ fontSize: 11, color: "#FFB645", flexWrap: 'wrap' }}>
{t('auth.agree.join', { ns: 'login' })}
</ThemedText>
<TouchableOpacity onPress={() => { setModalVisible(true); setModalType('privacy') }}>
<ThemedText style={{ fontSize: 11, color: "#FFB645", textDecorationLine: 'underline' }}>
{t('auth.agree.privacyPolicy', { ns: 'login' })}
</ThemedText>
</TouchableOpacity>
</View>
}
</View>
<PrivacyModal modalVisible={modalVisible} setModalVisible={setModalVisible} type={modalType} />
</ThemedView>
</ThemedView>
</ScrollView>
</KeyboardAvoidingView>
);
}
export default LoginScreen