for-legacy-web/src/controllers/client/ClientController.tsx

134 lines
3.2 KiB
TypeScript

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<string, Session>;
/**
* User ID of active session
*/
private current: Nullable<string>;
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;
}