import { action, computed, makeAutoObservable, ObservableMap } from "mobx"; import { Client, Nullable } from "revolt.js"; import Auth from "../../mobx/stores/Auth"; import { modalController } from "../modals/ModalController"; import Session from "./Session"; class ClientController { /** * API client */ private apiClient: Client; /** * Map of user IDs to sessions */ private sessions: ObservableMap; /** * User ID of active session */ private current: Nullable; constructor() { this.apiClient = new Client({ apiURL: import.meta.env.VITE_API_URL, }); this.sessions = new ObservableMap(); this.current = null; makeAutoObservable(this); this.logoutCurrent = this.logoutCurrent.bind(this); // Inject globally (window as any).clientController = this; } /** * Hydrate sessions and start client lifecycles. * @param auth Authentication store */ @action hydrate(auth: Auth) { for (const entry of auth.getAccounts()) { const user_id = entry.session.user_id!; const session = new Session(); this.sessions.set(user_id, session); session .emit({ action: "LOGIN", session: entry.session, }) .catch((error) => { if (error === "Forbidden" || error === "Unauthorized") { this.sessions.delete(user_id); auth.removeSession(user_id); modalController.push({ type: "signed_out" }); } }); } this.current = this.sessions.keys().next().value ?? null; } @computed getActiveSession() { return this.sessions.get(this.current!); } @computed getAnonymousClient() { return this.apiClient; } @computed getAvailableClient() { return this.getActiveSession()?.client ?? this.apiClient; } @computed isLoggedIn() { return this.current === null; } @action logout(user_id: string) { const session = this.sessions.get(user_id); if (session) { this.sessions.delete(user_id); if (user_id === this.current) { this.current = this.sessions.keys().next().value ?? null; } session.destroy(); } } @action logoutCurrent() { if (this.current) { this.logout(this.current); } } @action switchAccount(user_id: string) { this.current = user_id; } } export const clientController = new ClientController(); /** * Get the currently active session. * @returns Session */ export function useSession() { return clientController.getActiveSession(); } /** * Get the currently active client or an unauthorised * client for API requests, whichever is available. * @returns Revolt.js Client */ export function useClient() { return clientController.getAvailableClient(); } /** * Get unauthorised client for API requests. * @returns Revolt.js Client */ export function useApi() { return clientController.getAnonymousClient().api; }