You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

450 lines
12 KiB

import React, { useEffect, useState, useRef } from "react";
import {
View,
Text,
StyleSheet,
TouchableOpacity,
StatusBar,
Platform,
BackHandler,
Image,
Modal,
SafeAreaView,
} from "react-native";
import { useTranslation } from "react-i18next";
import { useNavigation } from "@react-navigation/native";
import type { NativeStackNavigationProp } from "@react-navigation/native-stack";
import fontSize from "../../utils/fontsizeUtils";
import EmailLoginModal from "./EmailLoginModal";
import PhoneLoginModal from "./PhoneLoginModal";
import * as WebBrowser from "expo-web-browser";
import * as AuthSession from "expo-auth-session";
import * as Linking from "expo-linking";
import * as Google from "expo-auth-session/providers/google";
WebBrowser.maybeCompleteAuthSession();
type RootStackParamList = {
Login: undefined;
EmailLogin: undefined;
MainTabs: { screen: string };
Google: undefined;
Home: { screen: string };
};
type LoginScreenProps = {
onClose?: () => void;
isModal?: boolean;
};
const CLIENT_ID =
"529750832779-osemooqkar78m8lhrn9dvbvi98fr4g08.apps.googleusercontent.com"; // from Google Cloud
const REDIRECT_URI = AuthSession.makeRedirectUri({
native: "brainnelapp://redirect",
});
export const LoginScreen = ({ onClose, isModal }: LoginScreenProps) => {
const { t } = useTranslation();
const navigation =
useNavigation<NativeStackNavigationProp<RootStackParamList>>();
// 全新的状态管理方式
const [emailModalVisible, setEmailModalVisible] = useState(false);
const [phoneModalVisible, setPhoneModalVisible] = useState(false);
// 防止多次触发
const isProcessingEmail = useRef(false);
const isProcessingPhone = useRef(false);
// 处理Android返回按钮
useEffect(() => {
const backAction = () => {
if (emailModalVisible) {
setEmailModalVisible(false);
return true;
}
if (phoneModalVisible) {
setPhoneModalVisible(false);
return true;
}
handleClose();
return true;
};
const backHandler = BackHandler.addEventListener(
"hardwareBackPress",
backAction
);
return () => backHandler.remove();
}, [emailModalVisible, phoneModalVisible]);
// 关闭主屏幕
const handleClose = () => {
if (isModal && onClose) {
onClose();
} else {
navigation.goBack();
}
};
const discovery = {
authorizationEndpoint: "https://accounts.google.com/o/oauth2/v2/auth",
tokenEndpoint: "https://oauth2.googleapis.com/token",
revocationEndpoint: "https://oauth2.googleapis.com/revoke",
};
const [request, response, handleGoogleLogin] = AuthSession.useAuthRequest(
{
clientId: CLIENT_ID,
scopes: ["openid", "profile", "email"],
redirectUri: REDIRECT_URI,
responseType: AuthSession.ResponseType.Code,
},
discovery
);
React.useEffect(() => {
if (response?.type === "success") {
const { code } = response.params;
console.log("授权码:", code);
}
}, [response]);
// 处理谷歌登录
// const handleGoogleLogin = async () => {
// // navigation.navigate("Google");
// };
// 处理Facebook登录
const handleFacebookLogin = () => {
// 处理Facebook登录
};
// 处理Apple登录
const handleAppleLogin = () => {
// 处理Apple登录
};
// 处理Instagram登录
const handleInstagramLogin = () => {
// 处理Instagram登录
};
// 显示邮箱登录
const showEmailModal = () => {
if (isProcessingEmail.current) return;
isProcessingEmail.current = true;
// 确保手机模态框已关闭
setPhoneModalVisible(false);
// 延迟打开邮箱模态框,避免冲突
setTimeout(() => {
setEmailModalVisible(true);
isProcessingEmail.current = false;
}, 100);
};
// 显示手机登录
const showPhoneModal = () => {
if (isProcessingPhone.current) return;
isProcessingPhone.current = true;
// 确保邮箱模态框已关闭
setEmailModalVisible(false);
// 延迟打开手机模态框,避免冲突
setTimeout(() => {
setPhoneModalVisible(true);
isProcessingPhone.current = false;
}, 100);
};
// 关闭邮箱登录
const hideEmailModal = () => {
console.log("Hiding email modal");
setEmailModalVisible(false);
};
// 关闭手机登录
const hidePhoneModal = () => {
console.log("Hiding phone modal");
setPhoneModalVisible(false);
};
// 处理忘记密码
const handleForgotPassword = () => {
// 处理忘记密码
};
return (
<SafeAreaView style={styles.safeArea}>
<StatusBar barStyle="light-content" backgroundColor="#0066FF" />
<View style={styles.safeAreaContent}>
{/* 顶部蓝色背景区域 */}
<View style={styles.blueHeader}>
<Text style={styles.logo}>brainnel</Text>
<View style={styles.features}>
<View style={styles.featureItem}>
<View style={styles.featureIconContainer}>
<Text style={styles.featureIcon}>💰</Text>
</View>
<Text style={styles.featureText}>{t("wholesalePrice")}</Text>
</View>
<View style={styles.featureItem}>
<View style={styles.featureIconContainer}>
<Text style={styles.featureIcon}>🚚</Text>
</View>
<Text style={styles.featureText}>{t("fastShipping")}</Text>
</View>
</View>
</View>
{/* 登录区域 */}
<View style={styles.loginContainer}>
<TouchableOpacity style={styles.closeButton} onPress={handleClose}>
<Text style={styles.closeButtonText}>×</Text>
</TouchableOpacity>
<View style={styles.titleContainer}>
<Text style={styles.subtitle}>{t("loginSubtitle")}</Text>
</View>
{/* 登录按钮 */}
<TouchableOpacity
style={styles.loginButton}
onPress={() => handleGoogleLogin()}
>
<View style={styles.loginButtonIcon}>
<Image
source={require("../../../assets/img/google.png")}
style={{ width: 20, height: 20 }}
/>
</View>
<Text style={styles.loginButtonText}>
{t("continueWithGoogle")}
</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.loginButton}
onPress={handleFacebookLogin}
>
<View style={[styles.loginButtonIcon, styles.facebookIcon]}>
<Text style={{ color: "#fff" }}>f</Text>
</View>
<Text style={styles.loginButtonText}>
{t("continueWithFacebook")}
</Text>
</TouchableOpacity>
{Platform.OS === "ios" && (
<TouchableOpacity
style={styles.loginButton}
onPress={handleAppleLogin}
>
<View style={[styles.loginButtonIcon, styles.appleIconBg]}>
<Text>🍎</Text>
</View>
<Text style={styles.loginButtonText}>
{t("continueWithApple")}
</Text>
</TouchableOpacity>
)}
<TouchableOpacity
style={styles.loginButton}
onPress={handleInstagramLogin}
>
<View style={[styles.loginButtonIcon, styles.instagramIcon]}>
<Text>📷</Text>
</View>
<Text style={styles.loginButtonText}>
{t("continueWithInstagram")}
</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.loginButton} onPress={showEmailModal}>
<View style={styles.loginButtonIcon}>
<Text></Text>
</View>
<Text style={styles.loginButtonText}>{t("continueWithEmail")}</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.loginButton} onPress={showPhoneModal}>
<View style={styles.loginButtonIcon}>
<Text>📱</Text>
</View>
<Text style={styles.loginButtonText}>{t("continueWithPhone")}</Text>
</TouchableOpacity>
{/* 忘记密码 */}
<TouchableOpacity
style={styles.forgotPassword}
onPress={handleForgotPassword}
>
<Text style={styles.forgotPasswordText}>{t("forgotPassword")}</Text>
</TouchableOpacity>
{/* 服务条款 */}
<View style={styles.termsContainer}>
<Text style={styles.terms}>
{t("termsText")}{" "}
<Text style={styles.link}>{t("termsOfUse")}</Text>
</Text>
<Text style={styles.terms}>
{t("and")} <Text style={styles.link}>{t("privacyPolicy")}</Text>
</Text>
</View>
</View>
</View>
{/* 邮箱登录模态框 - 直接渲染 */}
<EmailLoginModal visible={emailModalVisible} onClose={hideEmailModal} />
{/* 手机登录模态框 - 直接渲染 */}
<PhoneLoginModal visible={phoneModalVisible} onClose={hidePhoneModal} />
</SafeAreaView>
);
};
const styles = StyleSheet.create({
safeArea: {
flex: 1,
},
safeAreaContent: {
flex: 1,
paddingTop: 0,
},
container: {
flex: 1,
backgroundColor: "#FFF",
},
closeButton: {
position: "absolute",
top: 15,
left: 10,
width: 24,
height: 24,
justifyContent: "center",
alignItems: "center",
zIndex: 1,
},
closeButtonText: {
color: "#000",
fontSize: fontSize(24),
fontWeight: "300",
},
blueHeader: {
backgroundColor: "#0066FF",
paddingHorizontal: 20,
paddingBottom: 20,
paddingTop: Platform.OS === "ios" ? 60 : 40,
borderBottomLeftRadius: 24,
borderBottomRightRadius: 24,
},
logo: {
fontSize: fontSize(28),
fontWeight: "bold",
color: "#fff",
marginBottom: 15,
},
features: {
flexDirection: "row",
gap: 16,
},
featureItem: {
flexDirection: "row",
alignItems: "center",
gap: 8,
},
featureIconContainer: {
backgroundColor: "rgba(255, 255, 255, 0.2)",
borderRadius: 8,
width: 24,
height: 24,
justifyContent: "center",
alignItems: "center",
},
featureIcon: {
fontSize: fontSize(12),
},
featureText: {
fontSize: fontSize(14),
color: "#fff",
},
loginContainer: {
flex: 1,
paddingHorizontal: 20,
paddingTop: Platform.OS === "ios" ? 40 : 20,
},
titleContainer: {
alignItems: "center",
marginBottom: 30,
paddingTop: 20,
position: "relative",
},
subtitle: {
fontSize: fontSize(14),
color: "#666",
textAlign: "center",
},
loginButton: {
flexDirection: "row",
height: 50,
borderRadius: 25,
borderWidth: 1,
borderColor: "#E1E1E1",
alignItems: "center",
marginBottom: 12,
paddingHorizontal: 16,
backgroundColor: "#fff",
},
loginButtonIcon: {
width: 24,
height: 24,
borderRadius: 12,
justifyContent: "center",
alignItems: "center",
marginRight: 16,
},
facebookIcon: {
backgroundColor: "#3b5998",
},
appleIconBg: {
backgroundColor: "#000",
},
instagramIcon: {
backgroundColor: "#E1306C",
},
loginButtonText: {
flex: 1,
fontSize: fontSize(16),
color: "#000",
textAlign: "center",
marginRight: 16,
},
forgotPassword: {
alignItems: "center",
marginVertical: 20,
},
forgotPasswordText: {
color: "#0066FF",
fontSize: fontSize(14),
},
termsContainer: {
alignItems: "center",
marginTop: 10,
},
terms: {
fontSize: fontSize(12),
color: "#666",
textAlign: "center",
lineHeight: 18,
},
link: {
color: "#0066FF",
},
});
export default LoginScreen;