Spaces:
Running
Running
Anish-530
Fixed Mobile support. Added a new AI media detection mechanism by Farid, that creates geometric lines. Fixed logs
817ad83 | "use client"; | |
| import React, { createContext, useContext, useState, useEffect, useRef } from 'react'; | |
| import { usePathname } from 'next/navigation'; | |
| import { useRouter } from 'next/navigation'; | |
| import { apiLayer } from '@/lib/api'; | |
| type UserData = { | |
| id: number; | |
| email: string; | |
| name: string; | |
| is_admin: boolean; | |
| avatar_url?: string | null; | |
| google_avatar_url?: string | null; | |
| created_at?: string | null; | |
| }; | |
| type AuthContextType = { | |
| isAuthenticated: boolean; | |
| user: UserData | null; | |
| loading: boolean; | |
| logout: () => void; | |
| updateUser: (data: Partial<UserData>) => void; | |
| }; | |
| const AuthContext = createContext<AuthContextType>({ isAuthenticated: false, user: null, loading: true, logout: () => {}, updateUser: () => {} }); | |
| export function AuthProvider({ children }: { children: React.ReactNode }) { | |
| const [isAuthenticated, setIsAuthenticated] = useState(false); | |
| const [user, setUser] = useState<UserData | null>(null); | |
| const [loading, setLoading] = useState(true); | |
| // Guard against double-execution in React StrictMode / Next.js App Router | |
| // (router from useRouter() gets a new identity on every render, so we NEVER | |
| // put it in the dep array — we check auth exactly once on mount) | |
| const hasFetched = useRef(false); | |
| const router = useRouter(); | |
| const pathname = usePathname(); | |
| useEffect(() => { | |
| if (hasFetched.current) return; | |
| hasFetched.current = true; | |
| setLoading(true); | |
| apiLayer.getCurrentUser() | |
| .then((res) => { | |
| setUser(res.data); | |
| setIsAuthenticated(true); | |
| }) | |
| .catch(() => { | |
| setIsAuthenticated(false); | |
| setUser(null); | |
| // Only redirect to login from protected routes | |
| if (pathname?.includes('/dashboard') || pathname?.includes('/profile')) { | |
| router.push('/login'); | |
| } | |
| }) | |
| .finally(() => { | |
| setLoading(false); | |
| }); | |
| // Empty deps: intentional. Auth is checked once on mount, never on re-render. | |
| // eslint-disable-next-line react-hooks/exhaustive-deps | |
| }, []); | |
| const logout = () => { | |
| localStorage.removeItem("access_token"); | |
| setIsAuthenticated(false); | |
| setUser(null); | |
| hasFetched.current = false; // Allow re-check after logout | |
| router.push("/login"); | |
| }; | |
| const updateUser = (data: Partial<UserData>) => { | |
| setUser(prev => prev ? { ...prev, ...data } : null); | |
| }; | |
| return ( | |
| <AuthContext.Provider value={{ isAuthenticated, user, loading, logout, updateUser }}> | |
| {children} | |
| </AuthContext.Provider> | |
| ); | |
| } | |
| export const useAuth = () => useContext(AuthContext); | |