chore: clean up FSM code

This commit is contained in:
Paul Makles 2022-06-29 10:28:24 +01:00
parent 5f2311b09c
commit 8d505c9564
6 changed files with 44 additions and 20 deletions

View file

@ -2,7 +2,7 @@ import { observer } from "mobx-react-lite";
import { Text } from "preact-i18n"; import { Text } from "preact-i18n";
import { Banner } from "@revoltchat/ui"; import { Banner, Button, Column } from "@revoltchat/ui";
import { useSession } from "../../../controllers/client/ClientController"; import { useSession } from "../../../controllers/client/ClientController";
@ -18,15 +18,19 @@ function ConnectionStatus() {
} else if (session.state === "Disconnected") { } else if (session.state === "Disconnected") {
return ( return (
<Banner> <Banner>
<Text id="app.special.status.disconnected" /> <br /> <Column centred>
<a <Text id="app.special.status.disconnected" />
<Button
compact
palette="secondary"
onClick={() => onClick={() =>
session.emit({ session.emit({
action: "RETRY", action: "RETRY",
}) })
}> }>
<Text id="app.special.status.reconnect" /> <Text id="app.status.reconnect" />
</a> </Button>
</Column>
</Banner> </Banner>
); );
} else if (session.state === "Connecting") { } else if (session.state === "Connecting") {

View file

@ -1,6 +1,8 @@
import { action, computed, makeAutoObservable, ObservableMap } from "mobx"; import { action, computed, makeAutoObservable, ObservableMap } from "mobx";
import { Client, Nullable } from "revolt.js"; import { Client, Nullable } from "revolt.js";
import { injectController } from "../../lib/window";
import Auth from "../../mobx/stores/Auth"; import Auth from "../../mobx/stores/Auth";
import { modalController } from "../modals/ModalController"; import { modalController } from "../modals/ModalController";
@ -35,7 +37,7 @@ class ClientController {
this.logoutCurrent = this.logoutCurrent.bind(this); this.logoutCurrent = this.logoutCurrent.bind(this);
// Inject globally // Inject globally
(window as any).clientController = this; injectController("client", this);
} }
/** /**
@ -53,12 +55,14 @@ class ClientController {
.emit({ .emit({
action: "LOGIN", action: "LOGIN",
session: entry.session, session: entry.session,
apiUrl: entry.apiUrl,
}) })
.catch((error) => { .catch((error) => {
if (error === "Forbidden" || error === "Unauthorized") { if (error === "Forbidden" || error === "Unauthorized") {
this.sessions.delete(user_id); this.sessions.delete(user_id);
auth.removeSession(user_id); auth.removeSession(user_id);
modalController.push({ type: "signed_out" }); modalController.push({ type: "signed_out" });
session.destroy();
} }
}); });
} }

View file

@ -7,6 +7,7 @@ type Transition =
| { | {
action: "LOGIN"; action: "LOGIN";
session: SessionPrivate; session: SessionPrivate;
apiUrl?: string;
} }
| { | {
action: action:
@ -70,12 +71,12 @@ export default class Session {
}); });
} }
private createClient() { private createClient(apiUrl?: string) {
this.client = new Client({ this.client = new Client({
unreads: true, unreads: true,
autoReconnect: false, autoReconnect: false,
onPongTimeout: "EXIT", onPongTimeout: "EXIT",
apiURL: import.meta.env.VITE_API_URL, apiURL: apiUrl ?? import.meta.env.VITE_API_URL,
}); });
this.client.addListener("dropped", this.onDropped); this.client.addListener("dropped", this.onDropped);
@ -110,7 +111,7 @@ export default class Session {
case "LOGIN": { case "LOGIN": {
this.assert("Ready"); this.assert("Ready");
this.state = "Connecting"; this.state = "Connecting";
this.createClient(); this.createClient(data.apiUrl);
try { try {
await this.client!.useExistingSession(data.session); await this.client!.useExistingSession(data.session);
@ -135,10 +136,13 @@ export default class Session {
this.state = "Disconnected"; this.state = "Disconnected";
setTimeout(() => { setTimeout(() => {
// Check we are still disconnected before retrying.
if (this.state === "Disconnected") {
this.emit({ this.emit({
action: "RETRY", action: "RETRY",
}); });
}, 1500); }
}, 1000);
} }
break; break;

View file

@ -9,6 +9,7 @@ import type { Client, API } from "revolt.js";
import { ulid } from "ulid"; import { ulid } from "ulid";
import { determineLink } from "../../lib/links"; import { determineLink } from "../../lib/links";
import { injectController } from "../../lib/window";
import { getApplicationState } from "../../mobx/State"; import { getApplicationState } from "../../mobx/State";
@ -52,6 +53,9 @@ class ModalController<T extends Modal> {
rendered: computed, rendered: computed,
isVisible: computed, isVisible: computed,
}); });
// Inject globally
injectController("modal", this);
} }
/** /**

6
src/lib/window.ts Normal file
View file

@ -0,0 +1,6 @@
export function injectController(key: string, value: any) {
(window as any).controllers = {
...((window as any).controllers ?? {}),
[key]: value,
};
}

View file

@ -8,6 +8,7 @@ import Store from "../interfaces/Store";
interface Account { interface Account {
session: Session; session: Session;
apiUrl?: string;
} }
export interface Data { export interface Data {
@ -70,9 +71,10 @@ export default class Auth implements Store, Persistent<Data> {
/** /**
* Add a new session to the auth manager. * Add a new session to the auth manager.
* @param session Session * @param session Session
* @param apiUrl Custom API URL
*/ */
@action setSession(session: Session) { @action setSession(session: Session, apiUrl?: string) {
this.sessions.set(session.user_id, { session }); this.sessions.set(session.user_id, { session, apiUrl });
} }
/** /**