Full-featured PureRef-style collaborative canvas for game dev teams: - Layer panel with visibility, lock, drag reorder, group/ungroup (Ctrl+G/Shift+G) - Arrangement tools (grid, row, column) via right-click context menu - Copy to system clipboard (Ctrl+C writes PNG for external paste in Paint etc.) - Number shortcuts (1-5) for tool selection with visible shortcut badges - Premium dark UI across all pages (Login, Collections, Boards, Editor) - Socket.IO rooms for cursors, transforms, and presence notifications - MinIO image storage with backend proxy, drag/drop and paste upload
86 lines
1.8 KiB
TypeScript
86 lines
1.8 KiB
TypeScript
import React, { createContext, useContext, useState, useEffect, useCallback, ReactNode } from 'react';
|
|
import { getMe } from './api';
|
|
|
|
const TOKEN_KEY = 'refboard_token';
|
|
|
|
export function getToken(): string | null {
|
|
return localStorage.getItem(TOKEN_KEY);
|
|
}
|
|
|
|
export function setToken(token: string): void {
|
|
localStorage.setItem(TOKEN_KEY, token);
|
|
}
|
|
|
|
export function removeToken(): void {
|
|
localStorage.removeItem(TOKEN_KEY);
|
|
}
|
|
|
|
export function isAuthenticated(): boolean {
|
|
return !!getToken();
|
|
}
|
|
|
|
export interface User {
|
|
id: string;
|
|
email: string;
|
|
username: string;
|
|
display_name: string;
|
|
role: string;
|
|
}
|
|
|
|
interface AuthContextType {
|
|
user: User | null;
|
|
loading: boolean;
|
|
login: (token: string, user: User) => void;
|
|
logout: () => void;
|
|
}
|
|
|
|
export const AuthContext = createContext<AuthContextType>({
|
|
user: null,
|
|
loading: true,
|
|
login: () => {},
|
|
logout: () => {},
|
|
});
|
|
|
|
export function useAuth(): AuthContextType {
|
|
return useContext(AuthContext);
|
|
}
|
|
|
|
export function AuthProvider({ children }: { children: ReactNode }) {
|
|
const [user, setUser] = useState<User | null>(null);
|
|
const [loading, setLoading] = useState(true);
|
|
|
|
useEffect(() => {
|
|
const token = getToken();
|
|
if (token) {
|
|
getMe()
|
|
.then((res) => {
|
|
setUser(res.data.user || res.data);
|
|
})
|
|
.catch(() => {
|
|
removeToken();
|
|
})
|
|
.finally(() => {
|
|
setLoading(false);
|
|
});
|
|
} else {
|
|
setLoading(false);
|
|
}
|
|
}, []);
|
|
|
|
const login = useCallback((token: string, userData: User) => {
|
|
setToken(token);
|
|
setUser(userData);
|
|
}, []);
|
|
|
|
const logout = useCallback(() => {
|
|
removeToken();
|
|
setUser(null);
|
|
}, []);
|
|
|
|
return React.createElement(
|
|
AuthContext.Provider,
|
|
{ value: { user, loading, login, logout } },
|
|
children
|
|
);
|
|
}
|