diff --git a/src/components/navigation/items/ConnectionStatus.tsx b/src/components/navigation/items/ConnectionStatus.tsx index 517c5b03..46a9f6cc 100644 --- a/src/components/navigation/items/ConnectionStatus.tsx +++ b/src/components/navigation/items/ConnectionStatus.tsx @@ -2,7 +2,7 @@ import { observer } from "mobx-react-lite"; import { Text } from "preact-i18n"; -import { Banner } from "@revoltchat/ui"; +import { Banner, Button, Column } from "@revoltchat/ui"; import { useSession } from "../../../controllers/client/ClientController"; @@ -18,15 +18,19 @@ function ConnectionStatus() { } else if (session.state === "Disconnected") { return ( -
- - session.emit({ - action: "RETRY", - }) - }> - - + + + +
); } else if (session.state === "Connecting") { diff --git a/src/controllers/client/ClientController.tsx b/src/controllers/client/ClientController.tsx index df3216bd..be9497ce 100644 --- a/src/controllers/client/ClientController.tsx +++ b/src/controllers/client/ClientController.tsx @@ -1,6 +1,8 @@ import { action, computed, makeAutoObservable, ObservableMap } from "mobx"; import { Client, Nullable } from "revolt.js"; +import { injectController } from "../../lib/window"; + import Auth from "../../mobx/stores/Auth"; import { modalController } from "../modals/ModalController"; @@ -35,7 +37,7 @@ class ClientController { this.logoutCurrent = this.logoutCurrent.bind(this); // Inject globally - (window as any).clientController = this; + injectController("client", this); } /** @@ -53,12 +55,14 @@ class ClientController { .emit({ action: "LOGIN", session: entry.session, + apiUrl: entry.apiUrl, }) .catch((error) => { if (error === "Forbidden" || error === "Unauthorized") { this.sessions.delete(user_id); auth.removeSession(user_id); modalController.push({ type: "signed_out" }); + session.destroy(); } }); } diff --git a/src/controllers/client/Session.tsx b/src/controllers/client/Session.tsx index b19750e5..96c203b9 100644 --- a/src/controllers/client/Session.tsx +++ b/src/controllers/client/Session.tsx @@ -7,6 +7,7 @@ type Transition = | { action: "LOGIN"; session: SessionPrivate; + apiUrl?: string; } | { action: @@ -70,12 +71,12 @@ export default class Session { }); } - private createClient() { + private createClient(apiUrl?: string) { this.client = new Client({ unreads: true, autoReconnect: false, onPongTimeout: "EXIT", - apiURL: import.meta.env.VITE_API_URL, + apiURL: apiUrl ?? import.meta.env.VITE_API_URL, }); this.client.addListener("dropped", this.onDropped); @@ -110,7 +111,7 @@ export default class Session { case "LOGIN": { this.assert("Ready"); this.state = "Connecting"; - this.createClient(); + this.createClient(data.apiUrl); try { await this.client!.useExistingSession(data.session); @@ -135,10 +136,13 @@ export default class Session { this.state = "Disconnected"; setTimeout(() => { - this.emit({ - action: "RETRY", - }); - }, 1500); + // Check we are still disconnected before retrying. + if (this.state === "Disconnected") { + this.emit({ + action: "RETRY", + }); + } + }, 1000); } break; diff --git a/src/controllers/modals/ModalController.tsx b/src/controllers/modals/ModalController.tsx index 48bb810d..8102cab8 100644 --- a/src/controllers/modals/ModalController.tsx +++ b/src/controllers/modals/ModalController.tsx @@ -9,6 +9,7 @@ import type { Client, API } from "revolt.js"; import { ulid } from "ulid"; import { determineLink } from "../../lib/links"; +import { injectController } from "../../lib/window"; import { getApplicationState } from "../../mobx/State"; @@ -52,6 +53,9 @@ class ModalController { rendered: computed, isVisible: computed, }); + + // Inject globally + injectController("modal", this); } /** diff --git a/src/lib/window.ts b/src/lib/window.ts new file mode 100644 index 00000000..f1290106 --- /dev/null +++ b/src/lib/window.ts @@ -0,0 +1,6 @@ +export function injectController(key: string, value: any) { + (window as any).controllers = { + ...((window as any).controllers ?? {}), + [key]: value, + }; +} diff --git a/src/mobx/stores/Auth.ts b/src/mobx/stores/Auth.ts index 33799f7e..12574350 100644 --- a/src/mobx/stores/Auth.ts +++ b/src/mobx/stores/Auth.ts @@ -8,6 +8,7 @@ import Store from "../interfaces/Store"; interface Account { session: Session; + apiUrl?: string; } export interface Data { @@ -70,9 +71,10 @@ export default class Auth implements Store, Persistent { /** * Add a new session to the auth manager. * @param session Session + * @param apiUrl Custom API URL */ - @action setSession(session: Session) { - this.sessions.set(session.user_id, { session }); + @action setSession(session: Session, apiUrl?: string) { + this.sessions.set(session.user_id, { session, apiUrl }); } /**