| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168 |
- import { ReactNode, createContext, useEffect, useState } from 'react';
- import { useContext } from 'react';
- import { router, useSegments } from 'expo-router';
- import * as SecureStore from 'expo-secure-store';
- import axios from 'axios';
- import { EXPO_PUBLIC_API_URL } from '@env';
- import { User } from '../types/user';
- import { authenticationService } from '../service/authService';
- type AuthProvider = {
- user: User | null;
- login: (username: string, password: string, isBinding: boolean) => Promise<boolean>;
- logout: () => void;
- setUser: React.Dispatch<React.SetStateAction<User | null>>;
- };
- function useProtectedRoute(user: User | null) {
- const segments = useSegments();
- // 添加状态跟踪根布局是否已挂载
- const [isLayoutMounted, setIsLayoutMounted] = useState(false);
- const isUserEmpty = (user: User | null): boolean => {
- return !user || Object.values(user).every((value) => value === undefined);
- };
- useEffect(() => {
- // 标记根布局已挂载
- setIsLayoutMounted(true);
- }, []);
- useEffect(() => {
- // 等待根布局挂载完成且路由段准备好
- if (!isLayoutMounted || !segments.length) return;
- const inAuthGroup = segments[0] === '(auth)';
- const inPublicGroup = segments[0] === '(public)';
- if (isUserEmpty(user) && !inPublicGroup) {
- router.replace('/login');
- } else if (!isUserEmpty(user) && inPublicGroup) {
- router.replace('/(auth)/(tabs)/(home)/mainPage');
- }
- }, [user, segments, isLayoutMounted]); // 添加 isLayoutMounted 依赖
- }
- export const AuthContext = createContext<AuthProvider>({
- user: null,
- login: async () => false,
- logout: () => {},
- setUser: () => {}
- });
- export function useAuth() {
- const context = useContext(AuthContext);
- if (!context) {
- throw new Error('useAuth must be used within a <AuthProvider />');
- }
- return context;
- }
- export default function AuthProvider({ children }: { children: ReactNode }) {
- const [user, setUser] = useState<User | null>(null);
- useEffect(() => {
- const checkToken = async () => {
- const token = await SecureStore.getItemAsync('accessToken');
- if (token) {
- const userInfo = await getUserFromAccessToken();
- if (userInfo) {
- setUser(userInfo);
- }
- }
- };
- checkToken();
- }, []);
- const login = async (username: string, password: string, isBinding: boolean) => {
- try {
- const result = await authenticationService.phoneLogin(username, password, isBinding);
- if (result === 'login successful') {
- const token = await SecureStore.getItemAsync('accessToken');
- if (token) {
- const userInfo = await getUserFromAccessToken();
- if (userInfo) {
- setUser(userInfo);
- return 'login successful';
- }
- }
- return 'login successful';
- } else {
- return result;
- }
- } catch (error) {
- console.error('Login error:', error);
- return error;
- }
- };
- //this is urgent login, only for testing & debugging
- // const login = async (username: string, password: string, isBinding: boolean) => {
- // try {
- // const loggedInUser = {
- // accessToken:
- // 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiY3VzdG9tZXIiLCJjcmVhdGVkQXQiOiIyMDI0LTA5LTAzVDA2OjM4OjU3LjI5NloiLCJ1cGRhdGVkQXQiOiIyMDI0LTEyLTAyVDE3OjUwOjQyLjI1MloiLCJpZCI6IjA2ZTRkNjU0LTliNDEtNDExMy1hZjBmLTE5OTIzYjc0YzEwZSIsImZpcnN0bmFtZSI6bnVsbCwibGFzdG5hbWUiOm51bGwsIm5pY2tuYW1lIjoiVGVzdCAyIiwiZW1haWwiOiJ0ZXN0MkBnbWFpbC5jb20iLCJwaG9uZSI6NjgxMDAxMTYsImljX2NhcmQiOiIwMDAwMDAwMDAwMDAxNDk2Iiwid2FsbGV0Ijo5NzYwLCJpY29uX3VybCI6bnVsbCwicmVtYXJrIjpudWxsLCJhZGRyZXNzIjpudWxsLCJzdGF0dXNfZmsiOiIxIiwiZ2VuZGVyIjoibWFuIiwiYmlydGhkYXkiOiIwNC8wNi8xMSIsImljX2Nhcl9pZCI6bnVsbCwiaWF0IjoxNzMzMTkyNjgzLCJleHAiOjE3MzMxOTk4ODN9.1VvQacR5SJ1JiRlnmy_m5rcrKN8wXsPTZ9_QLas8CEQ',
- // refreshToken:
- // 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiY3VzdG9tZXIiLCJjcmVhdGVkQXQiOiIyMDI0LTA5LTAzVDA2OjM4OjU3LjI5NloiLCJ1cGRhdGVkQXQiOiIyMDI0LTEyLTAyVDE3OjUwOjQyLjI1MloiLCJpZCI6IjA2ZTRkNjU0LTliNDEtNDExMy1hZjBmLTE5OTIzYjc0YzEwZSIsImZpcnN0bmFtZSI6bnVsbCwibGFzdG5hbWUiOm51bGwsIm5pY2tuYW1lIjoiVGVzdCAyIiwiZW1haWwiOiJ0ZXN0MkBnbWFpbC5jb20iLCJwaG9uZSI6NjgxMDAxMTYsImljX2NhcmQiOiIwMDAwMDAwMDAwMDAxNDk2Iiwid2FsbGV0Ijo5NzYwLCJpY29uX3VybCI6bnVsbCwicmVtYXJrIjpudWxsLCJhZGRyZXNzIjpudWxsLCJzdGF0dXNfZmsiOiIxIiwiZ2VuZGVyIjoibWFuIiwiYmlydGhkYXkiOiIwNC8wNi8xMSIsImljX2Nhcl9pZCI6bnVsbCwiaWF0IjoxNzMzMTkyMjY5LCJleHAiOjE3MzY2NDgyNjl9.OrZqQyLkHL0eojesrn3xqoxIYatanjCX-GyXTcmNoys'
- // };
- // if (loggedInUser) {
- // //this is only for urgent login, uncomment getItemAsync after
- // await SecureStore.setItemAsync('accessToken', loggedInUser.accessToken);
- // const token = await SecureStore.getItemAsync('accessToken');
- // if (token) {
- // const userInfo = await getUserFromAccessToken();
- // if (userInfo) {
- // console.log('userInfouserInfouserInfouserInfouserInfouserInfo', userInfo);
- // setUser(userInfo);
- // }
- // }
- // return true;
- // } else {
- // return false;
- // }
- // } catch (error) {
- // console.error('Login error:', error);
- // return false;
- // }
- // };
- const getUserFromAccessToken = async () => {
- const token = await SecureStore.getItemAsync('accessToken');
- try {
- const res = await axios.get(`${EXPO_PUBLIC_API_URL}/clients/customer`, {
- headers: {
- Authorization: `Bearer ${token}`
- }
- });
- const items = {
- address: res.data.address,
- birthday: res.data.birthday,
- gender: res.data.gender,
- email: res.data.email,
- nickname: res.data.nickname,
- phone: res.data.phone,
- car: res.data.defaultCar.license_plate
- };
- return items;
- } catch (error) {
- console.error('GetUser Error:', error);
- }
- };
- const logout = async () => {
- try {
- await authenticationService.logout();
- await SecureStore.deleteItemAsync('accessToken');
- setUser(null);
- router.replace('/login');
- } catch (error) {
- console.log('error during logout', error);
- }
- };
- // console.log('user', user);
- useProtectedRoute(user);
- return <AuthContext.Provider value={{ user, login, logout, setUser }}>{children}</AuthContext.Provider>;
- }
|