mirror of
https://github.com/fromchat-messenger/web.git
synced 2026-09-22 19:15:08 +03:00
151 lines
5.1 KiB
TypeScript
151 lines
5.1 KiB
TypeScript
import { create } from "zustand";
|
|
import type { User } from "@/core/types";
|
|
import api from "@/core/api";
|
|
import { API_BASE_URL } from "@/core/config";
|
|
import { initialize, subscribe, isSupported } from "@/core/push-notifications/push-notifications";
|
|
import { onlineStatusManager } from "@/core/onlineStatusManager";
|
|
import { typingManager } from "@/core/typingManager";
|
|
import type { UserState } from "./types";
|
|
|
|
interface UserStore {
|
|
user: UserState;
|
|
setUser: (token: string, user: User) => void;
|
|
logout: () => Promise<void>;
|
|
restoreFromStorage: () => Promise<void>;
|
|
setSuspended: (reason: string) => void;
|
|
}
|
|
|
|
export const useUserStore = create<UserStore>((set) => ({
|
|
user: {
|
|
currentUser: null,
|
|
authToken: null,
|
|
isSuspended: false,
|
|
suspensionReason: null
|
|
},
|
|
setUser: (token: string, user: User) => {
|
|
set({
|
|
user: {
|
|
currentUser: user,
|
|
authToken: token,
|
|
isSuspended: user.suspended || false,
|
|
suspensionReason: user.suspension_reason || null
|
|
}
|
|
});
|
|
|
|
onlineStatusManager.setAuthToken(token);
|
|
typingManager.setAuthToken(token);
|
|
|
|
try {
|
|
localStorage.setItem('authToken', token);
|
|
localStorage.setItem('currentUser', JSON.stringify(user));
|
|
} catch (error) {
|
|
console.error('Failed to store credentials in localStorage:', error);
|
|
}
|
|
|
|
// Ping will be sent automatically on WebSocket reconnect
|
|
// No need to send here to avoid duplicate pings
|
|
},
|
|
logout: async () => {
|
|
const token = useUserStore.getState().user.authToken;
|
|
if (token) {
|
|
try {
|
|
await api.user.auth.logout(token);
|
|
} catch (error) {
|
|
console.error("Server logout failed:", error);
|
|
}
|
|
}
|
|
|
|
try {
|
|
localStorage.removeItem("authToken");
|
|
localStorage.removeItem("currentUser");
|
|
} catch (error) {
|
|
console.error("Failed to clear localStorage:", error);
|
|
}
|
|
|
|
onlineStatusManager.setAuthToken(null);
|
|
typingManager.setAuthToken(null);
|
|
onlineStatusManager.cleanup();
|
|
typingManager.cleanup();
|
|
|
|
set({
|
|
user: {
|
|
currentUser: null,
|
|
authToken: null,
|
|
isSuspended: false,
|
|
suspensionReason: null
|
|
}
|
|
});
|
|
},
|
|
restoreFromStorage: async () => {
|
|
try {
|
|
const token = localStorage.getItem('authToken');
|
|
|
|
if (token) {
|
|
const fullResponse = await fetch(`${API_BASE_URL}/user/profile`, {
|
|
headers: api.user.auth.getAuthHeaders(token, true)
|
|
});
|
|
if (fullResponse.ok) {
|
|
const user: User = await fullResponse.json();
|
|
api.user.auth.restoreKeys();
|
|
try {
|
|
await api.user.auth.syncPublicKeyToServerIfMissing(token);
|
|
} catch (e) {
|
|
console.error("Public key sync to server failed:", e);
|
|
}
|
|
|
|
if (user.suspended) {
|
|
set({
|
|
user: {
|
|
currentUser: user,
|
|
authToken: token,
|
|
isSuspended: true,
|
|
suspensionReason: user.suspension_reason || null
|
|
}
|
|
});
|
|
return;
|
|
}
|
|
|
|
set({
|
|
user: {
|
|
currentUser: user,
|
|
authToken: token,
|
|
isSuspended: false,
|
|
suspensionReason: null
|
|
}
|
|
});
|
|
|
|
onlineStatusManager.setAuthToken(token);
|
|
typingManager.setAuthToken(token);
|
|
|
|
// Ping will be sent automatically on WebSocket reconnect
|
|
// No need to send here to avoid duplicate pings
|
|
|
|
try {
|
|
if (isSupported()) {
|
|
const initialized = await initialize();
|
|
if (initialized) {
|
|
await subscribe(token);
|
|
}
|
|
}
|
|
} catch (e) {
|
|
console.error("Notification setup failed (restored):", e);
|
|
}
|
|
} else {
|
|
throw new Error("Unable to authenticate");
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.error('Failed to restore user from localStorage:', error);
|
|
localStorage.removeItem('authToken');
|
|
localStorage.removeItem('currentUser');
|
|
}
|
|
},
|
|
setSuspended: (reason: string) => set((state) => ({
|
|
user: {
|
|
...state.user,
|
|
isSuspended: true,
|
|
suspensionReason: reason
|
|
}
|
|
}))
|
|
}));
|