|
|
@@ -1,16 +1,32 @@
|
|
|
import 'react-native-gesture-handler';
|
|
|
|
|
|
import React, { createContext, useContext, useRef, useState } from 'react';
|
|
|
-import { Platform, StyleSheet, View } from 'react-native';
|
|
|
+import { Platform, StyleSheet, View, Alert } from 'react-native';
|
|
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
|
import { GestureHandlerRootView } from 'react-native-gesture-handler';
|
|
|
import { MMKV } from 'react-native-mmkv';
|
|
|
import { WebView } from 'react-native-webview';
|
|
|
|
|
|
+import { GoogleSignin } from '@react-native-google-signin/google-signin';
|
|
|
+import { appleAuth } from '@invertase/react-native-apple-authentication';
|
|
|
+import DeviceInfo from 'react-native-device-info';
|
|
|
+import { AUTH_CONFIG } from '@/config/auth';
|
|
|
+
|
|
|
+
|
|
|
import ApplicationNavigator from '@/navigation/Application';
|
|
|
import { ThemeProvider } from '@/theme';
|
|
|
import '@/translations';
|
|
|
|
|
|
+import * as RNIap from 'react-native-iap';
|
|
|
+
|
|
|
+const itemSubs = ['com.recipemuse.vip.monthly']; // 你的订阅ID
|
|
|
+
|
|
|
+
|
|
|
+// 在 DEFAULT_URL 常量下方添加以下常量
|
|
|
+const MESSAGE_PREFIX = 'NATIVE_LOGIN_';
|
|
|
+const LOGIN_SUCCESS = `${MESSAGE_PREFIX}SUCCESS`;
|
|
|
+const LOGIN_REQUEST = `${MESSAGE_PREFIX}REQUEST`;
|
|
|
+
|
|
|
export const queryClient = new QueryClient({
|
|
|
defaultOptions: {
|
|
|
mutations: {
|
|
|
@@ -42,7 +58,9 @@ export const useWebViewContext = () => {
|
|
|
};
|
|
|
|
|
|
// 配置常量
|
|
|
-const DEFAULT_URL = 'http://localhost:5173';
|
|
|
+// const DEFAULT_URL = 'http://localhost:5173';
|
|
|
+
|
|
|
+const DEFAULT_URL = 'http://10.13.51.57:5173';
|
|
|
|
|
|
// WebView用户代理
|
|
|
const USER_AGENT = Platform.select({
|
|
|
@@ -54,6 +72,158 @@ function App() {
|
|
|
const webViewRef = useRef<WebView>(null);
|
|
|
const [showWebView, setShowWebView] = useState(false);
|
|
|
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 发送消息到 WebView
|
|
|
+ */
|
|
|
+ const sendMessageToWebView = (webViewRef: React.RefObject<WebView>, message: any) => {
|
|
|
+ if (webViewRef.current) {
|
|
|
+ const messageString = typeof message === 'string' ? message : JSON.stringify(message);
|
|
|
+ // 使用更可靠的通信方式
|
|
|
+ webViewRef.current.postMessage(messageString);
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理来自 WebView 的消息
|
|
|
+ */
|
|
|
+ const handleWebViewMessage = (
|
|
|
+ event: any,
|
|
|
+ webViewRef: React.RefObject<WebView>,
|
|
|
+ ) => {
|
|
|
+ try {
|
|
|
+ const data = event.nativeEvent.data;
|
|
|
+ // 检查是否为登录请求
|
|
|
+ if (data === LOGIN_REQUEST) {
|
|
|
+ // 延迟执行登录以确保 WebView 已完全显示
|
|
|
+ handleLogin()
|
|
|
+ .then(() => {
|
|
|
+ // 登录成功后发送成功消息到 WebView
|
|
|
+ sendMessageToWebView(webViewRef, {
|
|
|
+ type: LOGIN_SUCCESS,
|
|
|
+ status: 'success',
|
|
|
+ message: '登录成功'
|
|
|
+ });
|
|
|
+ })
|
|
|
+ .catch((error) => {
|
|
|
+ // 登录失败时发送失败消息到 WebView
|
|
|
+ sendMessageToWebView(webViewRef, {
|
|
|
+ type: `${MESSAGE_PREFIX}ERROR`,
|
|
|
+ status: 'error',
|
|
|
+ message: error.message || '登录失败'
|
|
|
+ });
|
|
|
+ })
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('处理 WebView 消息时出错:', error);
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleLogin = async () => {
|
|
|
+ try {
|
|
|
+ const deviceId = await DeviceInfo.getUniqueId();
|
|
|
+ console.log('设备ID:', deviceId);
|
|
|
+
|
|
|
+
|
|
|
+ let reqData = null
|
|
|
+ if (Platform.OS === 'ios') {
|
|
|
+ // iOS使用Apple登录
|
|
|
+ reqData = await handleAppleLogin();
|
|
|
+ } else {
|
|
|
+ // Android使用Google登录
|
|
|
+ reqData = await handleGoogleLogin();
|
|
|
+ }
|
|
|
+
|
|
|
+ console.log('reqData 请求参数',reqData)
|
|
|
+ } catch (error) {
|
|
|
+ console.error('登录失败:', error);
|
|
|
+ Alert.alert('登录失败', '请稍后重试');
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+
|
|
|
+ const handleAppleLogin = async () => {
|
|
|
+ try {
|
|
|
+ // 执行Apple登录请求
|
|
|
+ const appleAuthRequestResponse = await appleAuth.performRequest({
|
|
|
+ requestedOperation: appleAuth.Operation.LOGIN,
|
|
|
+ requestedScopes: [appleAuth.Scope.EMAIL, appleAuth.Scope.FULL_NAME],
|
|
|
+ });
|
|
|
+
|
|
|
+ // 获取凭证状态
|
|
|
+ const credentialState = await appleAuth.getCredentialStateForUser(
|
|
|
+ appleAuthRequestResponse.user,
|
|
|
+ );
|
|
|
+
|
|
|
+ if (credentialState === appleAuth.State.AUTHORIZED) {
|
|
|
+ console.log('Apple登录成功:', appleAuthRequestResponse);
|
|
|
+ // Alert.alert('登录成功', `欢迎 ${appleAuthRequestResponse.fullName?.givenName || '用户'}`);
|
|
|
+ sendMessageToWebView(webViewRef, {
|
|
|
+ type: 'LOGIN_SUCCESS_IOS',
|
|
|
+ status: 'success',
|
|
|
+ message: '登录成功',
|
|
|
+ data: appleAuthRequestResponse
|
|
|
+ })
|
|
|
+ // return appleAuthRequestResponse
|
|
|
+ // appleAuthRequestResponse : {
|
|
|
+ // user: '001746.b066d194b82f46eaac8f3f26b9a915fc.0901',
|
|
|
+ // realUserStatus: 2,
|
|
|
+ // authorizedScopes: [],
|
|
|
+ // identityToken: 'eyJraWQiOiJIdlZJNkVzWlhKIiwiYWxnIjoiUlMyNTYifQ.eyJpc3MiOiJodHRwczovL2FwcGxlaWQuYXBwbGUuY29tIiwiYXVkIjoiY29tLmlwZWFraW5nLnJlY2lwZW11c2UiLCJleHAiOjE3NjIzMzMyNzcsImlhdCI6MTc2MjI0Njg3Nywic3ViIjoiMDAxNzQ2LmIwNjZkMTk0YjgyZjQ2ZWFhYzhmM2YyNmI5YTkxNWZjLjA5MDEiLCJub25jZSI6IjYyYTliNmQzMWI4M2EyMjdhYzA3MjI2ZDZiMmQxYTc1MTRhZTRiZjZjMjhlMjJjMmU4OTkwNTkzYTVkYzE5N2MiLCJjX2hhc2giOiIyZ0hUN1M1NHBWUExfeW52aHVrRGF3IiwiZW1haWwiOiIyNzYyMDM4NzZAcXEuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImF1dGhfdGltZSI6MTc2MjI0Njg3Nywibm9uY2Vfc3VwcG9ydGVkIjp0cnVlLCJyZWFsX3VzZXJfc3RhdHVzIjoyfQ.Tt2X4fBYYY5xMKSDZW8DoLsmDFzVw4AaTkMVdvruKgEOlYnBmW5MJAgCIz8iqMSFwq1008YOcpcdnAAd1J43J9HdDV-Rpg_ryEP76ph0MiynbWPPPMexz3ndxe4_ZS3s7BZdweWJuwJ9x6SqoFl01tEqs8jGEaJ13Z3byYZgsbzQxtqLzof4W1RcjLGrgj_xagjqimbex3PAgD7bIh2SUBJbhNjIK_RcNPNLQTQ4EGFwNmfG22sFUFqY5W6ipyZvk6gXGegXgnTYZpeAS1bc8UL4KBz4T4zRQMkN3uJezPD6A_IfJKSkHmwsXgPYfLNhScuO2wSBc4Q-UvuS_Y3nhg',
|
|
|
+ // authorizationCode: 'c9da4feae2b0248bea11861ca60088eb1.0.rrxuw.hLfeCQRQVY12lVyUyHIbtw',
|
|
|
+ // fullName: {
|
|
|
+ // namePrefix: null,
|
|
|
+ // givenName: '凯',
|
|
|
+ // nameSuffix: null,
|
|
|
+ // middleName: null,
|
|
|
+ // familyName: '周',
|
|
|
+ // nickname: null
|
|
|
+ // },
|
|
|
+ // email: '276203876@qq.com',
|
|
|
+ // state: null,
|
|
|
+ // nonce: '202K2RJL4_8SJmIS9AThnL6PGbMGzAz8'
|
|
|
+ // }
|
|
|
+
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('Apple登录失败:', error);
|
|
|
+ throw error;
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleGoogleLogin = async () => {
|
|
|
+ try {
|
|
|
+ // 配置Google登录
|
|
|
+ await GoogleSignin.configure({
|
|
|
+ webClientId: AUTH_CONFIG.GOOGLE.WEB_CLIENT_ID,
|
|
|
+ offlineAccess: true,
|
|
|
+ });
|
|
|
+
|
|
|
+ // 检查是否已登录
|
|
|
+ await GoogleSignin.hasPlayServices();
|
|
|
+
|
|
|
+ // 执行登录
|
|
|
+ const userInfo = await GoogleSignin.signIn();
|
|
|
+ console.log('Google登录成功:', userInfo);
|
|
|
+ Alert.alert('登录成功', `欢迎 ${userInfo.data?.user.name || '用户'}`);
|
|
|
+ // return userInfo
|
|
|
+ sendMessageToWebView(webViewRef, {
|
|
|
+ type: 'LOGIN_SUCCESS_ANDROID',
|
|
|
+ status: 'success',
|
|
|
+ message: '登录成功',
|
|
|
+ data: userInfo
|
|
|
+ })
|
|
|
+ } catch (error) {
|
|
|
+ console.error('Google登录失败:', error);
|
|
|
+ throw error;
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleInAppPurchase = async () => {
|
|
|
+
|
|
|
+ };
|
|
|
+
|
|
|
return (
|
|
|
<GestureHandlerRootView style={styles.container}>
|
|
|
<QueryClientProvider client={queryClient}>
|
|
|
@@ -66,6 +236,7 @@ function App() {
|
|
|
<View style={[
|
|
|
styles.webViewContainer,
|
|
|
showWebView ? styles.webViewVisible : styles.webViewHidden,
|
|
|
+ __DEV__ && showWebView ? styles.webViewDebug : null // 开发模式下添加调试样式
|
|
|
]}>
|
|
|
<WebView
|
|
|
ref={webViewRef}
|
|
|
@@ -77,6 +248,9 @@ function App() {
|
|
|
startInLoadingState={true}
|
|
|
scalesPageToFit={true}
|
|
|
allowsBackForwardNavigationGestures={Platform.OS === 'ios'}
|
|
|
+ onMessage={(event) => handleWebViewMessage(event, webViewRef)}
|
|
|
+ onError={(error) => console.error('WebView 错误:', error)}
|
|
|
+ onHttpError={(error) => console.error('WebView HTTP 错误:', error)}
|
|
|
/>
|
|
|
</View>
|
|
|
</View>
|
|
|
@@ -109,6 +283,14 @@ const styles = StyleSheet.create({
|
|
|
webView: {
|
|
|
flex: 1,
|
|
|
},
|
|
|
+ // 添加一个新的样式用于调试模式
|
|
|
+ webViewDebug: {
|
|
|
+ top: 20, // 留出顶部空间
|
|
|
+ left: 10, // 留出左侧空间
|
|
|
+ right: 10, // 留出右侧空间
|
|
|
+ bottom: 20, // 留出底部空间
|
|
|
+ borderRadius: 10, // 添加圆角以便识别
|
|
|
+ },
|
|
|
});
|
|
|
|
|
|
export default App;
|