import React, { useState, useEffect, useReducer, useMemo, createContext, useCallback, } from "react"; import { View, Image as NativeImage, TouchableOpacity } 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 StreamerPosts from "./screeens/StreamerPosts"; 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 CreatePost from "./screeens/CreatePost"; import WebWithHeader from "./screeens/WebWithHeader"; import WebWithoutHeader from "./screeens/WebWithoutHeader"; 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"; import PrivatyModal from "./components/PrivatyModal"; import * as Sentry from "@sentry/react-native"; const RootStack = createNativeStackNavigator(); export const AuthContext = createContext(""); SplashScreen.preventAutoHideAsync(); Sentry.init({ dsn: "https://decf8ef204a5d5144c27608bf86851ce@o4506958331904000.ingest.us.sentry.io/4506958351630336", debug: false, // If `true`, Sentry will try to print out useful debugging information if something goes wrong with sending the event. Set it to `false` in production }); const App = () => { //app主题 const MyTheme = { ...DefaultTheme, colors: { ...DefaultTheme.colors, background: "#07050A", }, }; //保存用户剪贴板内容 const [inviterCode, setInviterCode] = useState(); //未同意用户协议和隐私政策时展示隐私弹窗 const [isPrivatyModalOpen, setIsPrivatyModalOpen] = useState(false); //隐私弹窗是否同意 const [checked, setChecked] = useState(false); //如果是第一次打开app则展示隐私弹窗 useEffect(() => { const handlePrivatyModal = async () => { const notFirstTimeOpenApp = await get("not_first_time_open_app"); if (!notFirstTimeOpenApp) { setIsPrivatyModalOpen(true); save("not_first_time_open_app", 1); return; } }; handlePrivatyModal(); }, []); //获取环境变量 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, checked: checked, setChecked: setChecked, }), [inviterCode, checked] ); //控制开屏图片出现 const [appIsReady, setAppIsReady] = useState(false); //控制更新弹窗出现 const [isUpdateModalVisible, setIsUpdateModalVisible] = useState(false); //保存最新版本信息 const [versionData, setVersionData] = useState({}); useEffect(() => { async function prepare() { try { //重新获取设备和app信息 storeAppInfo(); const token = await get("token"); const account = await get("account"); const base = await baseRequest(); const signature = await generateSignature({ ...base, }); //检查当前token是否有效 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; if (!checked) return; //用户未同意隐私政策时不获取剪贴板信息 getClipboardContent(); }, [checked]); //登录后获取用户剪贴板内容 useEffect(() => { if (!state.isSignin) return; getClipboardContent(); }, [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()} /> ), 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()}> ), headerTransparent: true, title: "", })} /> ) : ( <> ({ headerLeft: () => ( navigation.goBack()} /> ), headerTitleStyle: { color: "white" }, headerStyle: { backgroundColor: "#07050A" }, })} /> )} { setIsPrivatyModalOpen(false); setChecked(true); }} /> ); }; export default Sentry.wrap(App);