mirror of
https://github.com/stoatchat/for-legacy-web.git
synced 2026-03-07 01:15:28 +00:00
feat: implement useClient from client controller
This commit is contained in:
@@ -1,11 +1,17 @@
|
||||
import { action, computed, makeAutoObservable, ObservableMap } from "mobx";
|
||||
import type { Nullable } from "revolt.js";
|
||||
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
|
||||
*/
|
||||
@@ -17,10 +23,19 @@ class ClientController {
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -29,12 +44,23 @@ class ClientController {
|
||||
*/
|
||||
@action hydrate(auth: Auth) {
|
||||
for (const entry of auth.getAccounts()) {
|
||||
const user_id = entry.session.user_id!;
|
||||
|
||||
const session = new Session();
|
||||
this.sessions.set(entry.session._id!, session);
|
||||
session.emit({
|
||||
action: "LOGIN",
|
||||
session: entry.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;
|
||||
@@ -44,6 +70,14 @@ class ClientController {
|
||||
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;
|
||||
}
|
||||
@@ -59,6 +93,41 @@ class ClientController {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ type Transition =
|
||||
|
||||
export default class Session {
|
||||
state: State = window.navigator.onLine ? "Ready" : "Offline";
|
||||
user_id: string | null = null;
|
||||
client: Client | null = null;
|
||||
|
||||
constructor() {
|
||||
@@ -83,6 +84,7 @@ export default class Session {
|
||||
|
||||
private destroyClient() {
|
||||
this.client!.removeAllListeners();
|
||||
this.user_id = null;
|
||||
this.client = null;
|
||||
}
|
||||
|
||||
@@ -101,7 +103,7 @@ export default class Session {
|
||||
}
|
||||
|
||||
@action async emit(data: Transition) {
|
||||
console.info("Handle event:", data);
|
||||
console.info(`[FSM ${this.user_id ?? "Anonymous"}]`, data);
|
||||
|
||||
switch (data.action) {
|
||||
// Login with session
|
||||
@@ -112,6 +114,7 @@ export default class Session {
|
||||
|
||||
try {
|
||||
await this.client!.useExistingSession(data.session);
|
||||
this.user_id = this.client!.user!._id;
|
||||
} catch (err) {
|
||||
this.state = "Ready";
|
||||
throw err;
|
||||
|
||||
@@ -1,18 +1,16 @@
|
||||
import { SubmitHandler, useForm } from "react-hook-form";
|
||||
|
||||
import { Text } from "preact-i18n";
|
||||
import { useContext, useState } from "preact/hooks";
|
||||
import { useState } from "preact/hooks";
|
||||
|
||||
import { Category, Error, Modal } from "@revoltchat/ui";
|
||||
|
||||
import { noopTrue } from "../../../lib/js";
|
||||
|
||||
import { useApplicationState } from "../../../mobx/State";
|
||||
|
||||
import { AppContext } from "../../../context/revoltjs/RevoltClient";
|
||||
import { takeError } from "../../../context/revoltjs/util";
|
||||
|
||||
import FormField from "../../../pages/login/FormField";
|
||||
import { useClient } from "../../client/ClientController";
|
||||
import { ModalProps } from "../types";
|
||||
|
||||
interface FormInputs {
|
||||
@@ -30,7 +28,7 @@ export default function ModifyAccount({
|
||||
field,
|
||||
...props
|
||||
}: ModalProps<"modify_account">) {
|
||||
const client = useApplicationState().client!;
|
||||
const client = useClient();
|
||||
const [processing, setProcessing] = useState(false);
|
||||
const { handleSubmit, register, errors } = useForm<FormInputs>();
|
||||
const [error, setError] = useState<string | undefined>(undefined);
|
||||
|
||||
Reference in New Issue
Block a user