import React, { useState, useEffect, useRef, useReducer, useMemo, createContext, useCallback, } from "react"; import { View, AppState } from "react-native"; import * as SplashScreen from "expo-splash-screen"; import HomeTab from "./screeens/HomeTab"; import Login from "./screeens/Login"; import StreamerProfile from "./screeens/StreamerProfile"; import UserProfile from "./screeens/UserProfile"; import { createNativeStackNavigator } from "@react-navigation/native-stack"; import { NavigationContainer, DefaultTheme } from "@react-navigation/native"; import { SafeAreaProvider } from "react-native-safe-area-context"; import { TailwindProvider } from "tailwind-rn"; import utilities from "./tailwind.json"; import ForgetPassword from "./screeens/Login/ForgetPassword"; import SetPassword from "./screeens/Login/SetPassword"; import Toast from "react-native-toast-message"; import loginReducer from "./utils/loginReducer"; import MessageDetail from "./screeens/Messages/MessageDetail"; import EditUserProfile from "./screeens/EditUserProfile"; import Wallet from "./screeens/Wallet"; import UnlockedWechat from "./screeens/UnlockedWechat"; import EditStreamerProfile from "./screeens/EditStreamerProfile"; import Relationship from "./screeens/Relationship"; import StreamerVerification from "./screeens/StreamerVerification"; import EditPlatformOrder from "./screeens/EditPlatformOrder"; import StreamerInviteUser from "./screeens/StreamerInviteUser"; import Setting from "./screeens/Setting"; import WechatWaitingToAdd from "./screeens/WechatWaitingToAdd"; import Search from "./screeens/Search"; import WebWithHeader from "./screeens/WebWithHeader"; import UpdateModal from "./components/UpdateModal"; import StreamerNavigatorModal from "./components/StreamerNavigatorModal"; import { Icon } from "@rneui/themed"; import { StatusBar } from "expo-status-bar"; import { save, get, remove, storeAppInfo } from "./utils/storeInfo"; import baseRequest from "./utils/baseRequest"; import { generateSignature } from "./utils/crypto"; import * as Clipboard from "expo-clipboard"; const RootStack = createNativeStackNavigator(); export const AuthContext = createContext(""); SplashScreen.preventAutoHideAsync(); export default function App() { //app主题 const MyTheme = { ...DefaultTheme, colors: { ...DefaultTheme.colors, background: "#07050A", }, }; //保存用户剪贴板内容 const [inviterCode, setInviterCode] = useState(); //获取环境变量 const apiUrl = process.env.EXPO_PUBLIC_API_URL; //登录逻辑 const [state, dispatch] = useReducer(loginReducer, { isSignin: false, userToken: null, }); const authContext = useMemo( () => ({ signIn: async (data, mobilePhone, regionCode) => { await save("token", data.data.token); await save("account", data.data.account); await save("mobile_phone", mobilePhone); await save("region_code", regionCode); dispatch({ type: "SIGN_IN", token: data.data.token }); }, signOut: async () => { const base = await baseRequest(); const account = await get("account"); const signature = await generateSignature({ mid: account?.mid, ...base, }); try { await fetch(`${apiUrl}/api/login/logout?signature=${signature}`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ mid: account?.mid, ...base, }), }); await remove("token"); await remove("account"); } catch (error) { console.error(error); } finally { dispatch({ type: "SIGN_OUT" }); } }, inviterCode: inviterCode, }), [inviterCode] ); //控制开屏图片出现 const [appIsReady, setAppIsReady] = useState(false); //控制更新弹窗出现 const [isUpdateModalVisible, setIsUpdateModalVisible] = useState(false); //保存最新版本信息 const [versionData, setVersionData] = useState({}); useEffect(() => { async function prepare() { await storeAppInfo(); try { const token = await get("token"); const account = await get("account"); const base = await baseRequest(); const signature = await generateSignature({ ...base, }); if (token && account) { const response = await fetch( `${apiUrl}/api/login/validate?signature=${signature}`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ ...base, }), } ); const data = await response.json(); if (data.ret === 1) { dispatch({ type: "SIGN_IN", token: token }); } } //检查更新 const checkUpdataResponse = await fetch( `${apiUrl}/api/version/is_there_a_new_version_available?signature=${signature}`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ ...base, }), } ); const checkUpdataData = await checkUpdataResponse.json(); if (checkUpdataData.ret === -1) { return; } if (checkUpdataData.data.result) { setIsUpdateModalVisible(true); setVersionData(checkUpdataData.data); } } catch (e) { console.warn(e); } finally { setAppIsReady(true); } } prepare(); }, []); //获取用户剪贴板内容 const getClipboardContent = useCallback(async () => { const content = await Clipboard.getStringAsync(); const pattern = /https:\/\/tiefen\.fun\/(\d+)/; const match = content.match(pattern); if (match && match[1]) { const intInviterCode = parseInt(match[1], 10); setInviterCode(intInviterCode); await Clipboard.setStringAsync(""); return; } setInviterCode(null); }, []); //当用户未登录时,获取剪贴板内容,用于绑定邀请人 useEffect(() => { if (state.isSignin) return; getClipboardContent(); }, []); //每次从后台切换到前台时,获取用户剪贴板内容 const appState = useRef(AppState.currentState); useEffect(() => { if (!state.isSignin) return; const subscription = AppState.addEventListener("change", (nextAppState) => { if ( appState.current.match(/inactive|background/) && nextAppState === "active" ) { getClipboardContent(); } appState.current = nextAppState; }); return () => { subscription.remove(); }; }, [state.isSignin]); //当用户已经登录,查看根据剪贴板内容展示主播Modal const [streamerNavigatorModalStatus, setStreamerNavigatorModalStatus] = useState({ open: false, data: {}, }); useEffect(() => { const getInviterData = async () => { //获取主播数据 if (!inviterCode) return; if (!state.isSignin) return; if (isUpdateModalVisible) return; try { const base = await baseRequest(); const signature = await generateSignature({ user_id: inviterCode, ...base, }); const inviterResponse = await fetch( `${apiUrl}/api/streamer/list_ext_by_user_id?signature=${signature}`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ user_id: inviterCode, ...base, }), } ); const inviterData = await inviterResponse.json(); if (inviterData.ret === -1) { return; } setStreamerNavigatorModalStatus({ open: true, data: inviterData.data.streamer_ext, }); } catch (e) { console.warn(e); } }; getInviterData(); }, [state.isSignin, inviterCode, isUpdateModalVisible]); //展示和隐藏splash const onLayoutRootView = useCallback(async () => { if (appIsReady) { await SplashScreen.hideAsync(); } }, [appIsReady]); if (!appIsReady) { return null; } return ( {state.isSignin ? ( <> ({ headerLeft: () => ( navigation.goBack()} /> ), headerRight: () => ( ), headerTransparent: true, title: "", })} /> ({ headerLeft: () => ( navigation.goBack()} /> ), headerTransparent: true, title: "", })} /> ({ headerLeft: () => ( navigation.goBack()} /> ), title: "待添加微信", headerTitleStyle: { color: "white" }, headerStyle: { backgroundColor: "#07050A" }, })} /> ({ headerLeft: () => ( navigation.goBack()} /> ), title: "", headerTitleStyle: { color: "white" }, headerStyle: { backgroundColor: "#07050A" }, })} /> ({ headerLeft: () => ( navigation.goBack()} /> ), headerTransparent: true, title: "我的钱包", headerTitleStyle: { color: "white" }, })} /> ({ headerLeft: () => ( navigation.goBack()} /> ), title: "关系", headerTitleStyle: { color: "white" }, headerStyle: { backgroundColor: "#07050A" }, })} /> ({ headerLeft: () => ( navigation.goBack()} /> ), title: "已解锁微信", headerTitleStyle: { color: "white" }, headerStyle: { backgroundColor: "#07050A" }, })} /> ({ headerLeft: () => ( navigation.goBack()} /> ), title: "编辑主页", headerTitleStyle: { color: "white" }, headerStyle: { backgroundColor: "#07050A" }, })} /> ({ headerLeft: () => ( navigation.goBack()} /> ), title: "编辑平台", headerTitleStyle: { color: "white" }, headerStyle: { backgroundColor: "#07050A" }, })} /> ({ headerLeft: () => ( navigation.goBack()} /> ), title: "邀请分成", headerTitleStyle: { color: "white" }, headerStyle: { backgroundColor: "#07050A" }, })} /> ({ headerLeft: () => ( navigation.goBack()} /> ), headerTitleStyle: { color: "white" }, headerStyle: { backgroundColor: "#07050A" }, })} /> ) : ( <> ({ headerLeft: () => ( navigation.goBack()} /> ), headerTitleStyle: { color: "white" }, headerStyle: { backgroundColor: "#07050A" }, })} /> )} ); }