mirror of
https://github.com/revoltchat/revite.git
synced 2024-11-09 16:53:36 -05:00
chore: deprecate RevoltClient
context
This commit is contained in:
parent
0e86f19da2
commit
0261fec676
13 changed files with 118 additions and 108 deletions
|
@ -4,7 +4,7 @@ import { observer } from "mobx-react-lite";
|
|||
import { useParams } from "react-router-dom";
|
||||
import { Channel, Server, User, API } from "revolt.js";
|
||||
|
||||
import { useEffect, useState } from "preact/hooks";
|
||||
import { useEffect, useLayoutEffect, useState } from "preact/hooks";
|
||||
|
||||
import {
|
||||
useSession,
|
||||
|
|
|
@ -8,12 +8,12 @@ import { Preloader, UIProvider } from "@revoltchat/ui";
|
|||
|
||||
import { hydrateState } from "../mobx/State";
|
||||
|
||||
import Binder from "../controllers/client/jsx/Binder";
|
||||
import ModalRenderer from "../controllers/modals/ModalRenderer";
|
||||
import Locale from "./Locale";
|
||||
import Theme from "./Theme";
|
||||
import { history } from "./history";
|
||||
import Intermediate from "./intermediate/Intermediate";
|
||||
import Client from "./revoltjs/RevoltClient";
|
||||
import SyncManager from "./revoltjs/SyncManager";
|
||||
|
||||
const uiContext = {
|
||||
|
@ -41,10 +41,10 @@ export default function Context({ children }: { children: Children }) {
|
|||
<UIProvider value={uiContext}>
|
||||
<Locale>
|
||||
<Intermediate>
|
||||
<Client>
|
||||
<Binder>
|
||||
{children}
|
||||
<SyncManager />
|
||||
</Client>
|
||||
{<SyncManager />}
|
||||
</Binder>
|
||||
</Intermediate>
|
||||
<ModalRenderer />
|
||||
</Locale>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { observer } from "mobx-react-lite";
|
||||
import { Redirect } from "react-router-dom";
|
||||
|
||||
import { useSession } from "../../controllers/client/ClientController";
|
||||
import { clientController } from "../../controllers/client/ClientController";
|
||||
|
||||
interface Props {
|
||||
auth?: boolean;
|
||||
|
@ -9,16 +10,17 @@ interface Props {
|
|||
children: Children;
|
||||
}
|
||||
|
||||
export const CheckAuth = (props: Props) => {
|
||||
const session = useSession();
|
||||
export const CheckAuth = observer((props: Props) => {
|
||||
const loggedIn = clientController.isLoggedIn();
|
||||
|
||||
if (props.auth && !session?.ready) {
|
||||
// Redirect if logged out on authenticated page or vice-versa.
|
||||
if (props.auth && !loggedIn) {
|
||||
if (props.blockRender) return null;
|
||||
return <Redirect to="/login" />;
|
||||
} else if (!props.auth && session?.ready) {
|
||||
} else if (!props.auth && loggedIn) {
|
||||
if (props.blockRender) return null;
|
||||
return <Redirect to="/" />;
|
||||
}
|
||||
|
||||
return <>{props.children}</>;
|
||||
};
|
||||
});
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
/* eslint-disable react-hooks/rules-of-hooks */
|
||||
import { observer } from "mobx-react-lite";
|
||||
|
||||
import { useEffect } from "preact/hooks";
|
||||
|
||||
import { Preloader } from "@revoltchat/ui";
|
||||
|
||||
import { useApplicationState } from "../../mobx/State";
|
||||
|
||||
import { clientController } from "../../controllers/client/ClientController";
|
||||
|
||||
type Props = {
|
||||
children: Children;
|
||||
};
|
||||
|
||||
export default observer(({ children }: Props) => {
|
||||
const session = clientController.getActiveSession();
|
||||
if (session) {
|
||||
if (!session.ready) return <Preloader type="spinner" />;
|
||||
|
||||
const client = session.client!;
|
||||
const state = useApplicationState();
|
||||
useEffect(() => state.registerListeners(client), [state, client]);
|
||||
}
|
||||
|
||||
return <>{children}</>;
|
||||
});
|
|
@ -58,8 +58,9 @@ class ClientController {
|
|||
}
|
||||
|
||||
@action pickNextSession() {
|
||||
this.current =
|
||||
this.current ?? this.sessions.keys().next().value ?? null;
|
||||
this.switchAccount(
|
||||
this.current ?? this.sessions.keys().next().value ?? null,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -82,6 +83,15 @@ class ClientController {
|
|||
return this.sessions.get(this.current!);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the currently ready client
|
||||
* @returns Ready Client
|
||||
*/
|
||||
@computed getReadyClient() {
|
||||
const session = this.getActiveSession();
|
||||
return session && session.ready ? session.client! : undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an unauthenticated instance of the Revolt.js Client
|
||||
* @returns API Client
|
||||
|
@ -111,7 +121,15 @@ class ClientController {
|
|||
* @returns Whether we are logged in
|
||||
*/
|
||||
@computed isLoggedIn() {
|
||||
return this.current === null;
|
||||
return this.current !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether we are currently ready
|
||||
* @returns Whether we are ready to render
|
||||
*/
|
||||
@computed isReady() {
|
||||
return this.getActiveSession()?.ready;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -127,6 +145,7 @@ class ClientController {
|
|||
|
||||
const session = new Session();
|
||||
this.sessions.set(user_id, session);
|
||||
this.pickNextSession();
|
||||
|
||||
session
|
||||
.emit({
|
||||
|
@ -144,8 +163,6 @@ class ClientController {
|
|||
session.destroy();
|
||||
}
|
||||
});
|
||||
|
||||
this.pickNextSession();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -270,6 +270,6 @@ export default class Session {
|
|||
* @returns Boolean
|
||||
*/
|
||||
@computed get ready() {
|
||||
return this.client?.user;
|
||||
return !!this.client?.user;
|
||||
}
|
||||
}
|
||||
|
|
27
src/controllers/client/jsx/Binder.tsx
Normal file
27
src/controllers/client/jsx/Binder.tsx
Normal file
|
@ -0,0 +1,27 @@
|
|||
import { observer } from "mobx-react-lite";
|
||||
|
||||
import { useEffect } from "preact/hooks";
|
||||
|
||||
import { Preloader } from "@revoltchat/ui";
|
||||
|
||||
import { state } from "../../../mobx/State";
|
||||
|
||||
import { clientController } from "../ClientController";
|
||||
|
||||
/**
|
||||
* Prevent render until the client is ready to display.
|
||||
* Also binds listeners from state to the current client.
|
||||
*/
|
||||
const Binder: React.FC = ({ children }) => {
|
||||
const client = clientController.getReadyClient();
|
||||
useEffect(() => state.registerListeners(client!), [client]);
|
||||
|
||||
// Block render if client is getting ready to work.
|
||||
if (clientController.isLoggedIn() && !clientController.isReady()) {
|
||||
return <Preloader type="spinner" />;
|
||||
}
|
||||
|
||||
return <>{children}</>;
|
||||
};
|
||||
|
||||
export default observer(Binder);
|
|
@ -1,8 +1,6 @@
|
|||
/* eslint-disable react-hooks/rules-of-hooks */
|
||||
import { action, makeAutoObservable } from "mobx";
|
||||
import { Channel } from "revolt.js";
|
||||
import { Message } from "revolt.js";
|
||||
import { Nullable } from "revolt.js";
|
||||
import { Channel, Message, Nullable } from "revolt.js";
|
||||
|
||||
import { SimpleRenderer } from "./simple/SimpleRenderer";
|
||||
import { RendererRoutines, ScrollState } from "./types";
|
||||
|
|
|
@ -47,8 +47,6 @@ export default class State {
|
|||
private persistent: [string, Persistent<unknown>][] = [];
|
||||
private disabled: Set<string> = new Set();
|
||||
|
||||
client?: Client;
|
||||
|
||||
/**
|
||||
* Construct new State.
|
||||
*/
|
||||
|
@ -67,14 +65,10 @@ export default class State {
|
|||
this.plugins = new Plugins(this);
|
||||
this.ordering = new Ordering(this);
|
||||
|
||||
makeAutoObservable(this, {
|
||||
client: false,
|
||||
});
|
||||
makeAutoObservable(this);
|
||||
|
||||
this.register();
|
||||
this.setDisabled = this.setDisabled.bind(this);
|
||||
|
||||
this.client = undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -138,11 +132,11 @@ export default class State {
|
|||
registerListeners(client?: Client) {
|
||||
// If a client is present currently, expose it and provide it to plugins.
|
||||
if (client) {
|
||||
this.client = client;
|
||||
// this.client = client;
|
||||
this.plugins.onClient(client);
|
||||
|
||||
// Register message listener for clearing queue.
|
||||
this.client.addListener("message", this.queue.onMessage);
|
||||
// this.client.addListener("message", this.queue.onMessage);
|
||||
}
|
||||
|
||||
// Register all the listeners required for saving and syncing state.
|
||||
|
@ -228,13 +222,13 @@ export default class State {
|
|||
});
|
||||
|
||||
return () => {
|
||||
// Remove any listeners attached to client.
|
||||
/*// Remove any listeners attached to client.
|
||||
if (client) {
|
||||
client.removeListener("message", this.queue.onMessage);
|
||||
}
|
||||
|
||||
// Stop exposing the client.
|
||||
this.client = undefined;
|
||||
this.client = undefined;*/
|
||||
|
||||
// Wipe all listeners.
|
||||
listeners.forEach((x) => x());
|
||||
|
|
|
@ -2,6 +2,7 @@ import { action, computed, makeAutoObservable } from "mobx";
|
|||
|
||||
import { reorder } from "@revoltchat/ui";
|
||||
|
||||
import { clientController } from "../../controllers/client/ClientController";
|
||||
import State from "../State";
|
||||
import Persistent from "../interfaces/Persistent";
|
||||
import Store from "../interfaces/Store";
|
||||
|
@ -63,18 +64,19 @@ export default class Ordering implements Store, Persistent<Data>, Syncable {
|
|||
* All known servers with ordering applied
|
||||
*/
|
||||
@computed get orderedServers() {
|
||||
const known = new Set(this.state.client?.servers.keys() ?? []);
|
||||
const client = clientController.getReadyClient();
|
||||
const known = new Set(client?.servers.keys() ?? []);
|
||||
const ordered = [...this.servers];
|
||||
|
||||
const out = [];
|
||||
for (const id of ordered) {
|
||||
if (known.delete(id)) {
|
||||
out.push(this.state.client!.servers.get(id)!);
|
||||
out.push(client!.servers.get(id)!);
|
||||
}
|
||||
}
|
||||
|
||||
for (const id of known) {
|
||||
out.push(this.state.client!.servers.get(id)!);
|
||||
out.push(client!.servers.get(id)!);
|
||||
}
|
||||
|
||||
return out;
|
||||
|
|
|
@ -59,7 +59,7 @@ type Plugin = {
|
|||
|
||||
type Instance = {
|
||||
format: 1;
|
||||
onClient?: (client: Client) => {};
|
||||
onClient?: (client: Client) => void;
|
||||
onUnload?: () => void;
|
||||
};
|
||||
|
||||
|
@ -124,7 +124,7 @@ export default class Plugins implements Store, Persistent<Data> {
|
|||
* @param id Plugin Id
|
||||
*/
|
||||
@computed get(namespace: string, id: string) {
|
||||
return this.plugins.get(`${namespace }/${ id}`);
|
||||
return this.plugins.get(`${namespace}/${id}`);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -133,7 +133,7 @@ export default class Plugins implements Store, Persistent<Data> {
|
|||
* @returns Plugin Instance
|
||||
*/
|
||||
private getInstance(plugin: Pick<Plugin, "namespace" | "id">) {
|
||||
return this.instances.get(`${plugin.namespace }/${ plugin.id}`);
|
||||
return this.instances.get(`${plugin.namespace}/${plugin.id}`);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -159,7 +159,7 @@ export default class Plugins implements Store, Persistent<Data> {
|
|||
this.unload(plugin.namespace, plugin.id);
|
||||
}
|
||||
|
||||
this.plugins.set(`${plugin.namespace }/${ plugin.id}`, plugin);
|
||||
this.plugins.set(`${plugin.namespace}/${plugin.id}`, plugin);
|
||||
|
||||
if (typeof plugin.enabled === "undefined" || plugin) {
|
||||
this.load(plugin.namespace, plugin.id);
|
||||
|
@ -173,7 +173,7 @@ export default class Plugins implements Store, Persistent<Data> {
|
|||
*/
|
||||
remove(namespace: string, id: string) {
|
||||
this.unload(namespace, id);
|
||||
this.plugins.delete(`${namespace }/${ id}`);
|
||||
this.plugins.delete(`${namespace}/${id}`);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -186,7 +186,7 @@ export default class Plugins implements Store, Persistent<Data> {
|
|||
if (!plugin) throw "Unknown plugin!";
|
||||
|
||||
try {
|
||||
const ns = `${plugin.namespace }/${ plugin.id}`;
|
||||
const ns = `${plugin.namespace}/${plugin.id}`;
|
||||
|
||||
const instance: Instance = eval(plugin.entrypoint)();
|
||||
this.instances.set(ns, {
|
||||
|
@ -198,10 +198,6 @@ export default class Plugins implements Store, Persistent<Data> {
|
|||
...plugin,
|
||||
enabled: true,
|
||||
});
|
||||
|
||||
if (this.state.client) {
|
||||
instance.onClient?.(this.state.client);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Failed to load ${namespace}/${id}!`);
|
||||
console.error(error);
|
||||
|
@ -217,7 +213,7 @@ export default class Plugins implements Store, Persistent<Data> {
|
|||
const plugin = this.get(namespace, id);
|
||||
if (!plugin) throw "Unknown plugin!";
|
||||
|
||||
const ns = `${plugin.namespace }/${ plugin.id}`;
|
||||
const ns = `${plugin.namespace}/${plugin.id}`;
|
||||
const loaded = this.getInstance(plugin);
|
||||
if (loaded) {
|
||||
loaded.onUnload?.();
|
||||
|
|
|
@ -76,12 +76,6 @@ const Routes = styled.div.attrs({ "data-component": "routes" })<{
|
|||
|
||||
background: var(--primary-background);
|
||||
|
||||
/*background-color: rgba(
|
||||
var(--primary-background-rgb),
|
||||
max(var(--min-opacity), 0.75)
|
||||
);*/
|
||||
//backdrop-filter: blur(10px);
|
||||
|
||||
${() =>
|
||||
isTouchscreenDevice &&
|
||||
css`
|
||||
|
|
|
@ -15,44 +15,51 @@ const Login = lazy(() => import("./login/Login"));
|
|||
const ConfirmDelete = lazy(() => import("./login/ConfirmDelete"));
|
||||
const RevoltApp = lazy(() => import("./RevoltApp"));
|
||||
|
||||
const LoadSuspense: React.FC = ({ children }) => (
|
||||
// @ts-expect-error Typing issue between Preact and Preact.
|
||||
<Suspense fallback={<Preloader type="ring" />}>{children}</Suspense>
|
||||
);
|
||||
|
||||
export function App() {
|
||||
return (
|
||||
<ErrorBoundary section="client">
|
||||
<Context>
|
||||
<Masks />
|
||||
{/*
|
||||
// @ts-expect-error typings mis-match between preact... and preact? */}
|
||||
<Suspense fallback={<Preloader type="spinner" />}>
|
||||
<Switch>
|
||||
<Route path="/login/verify/:token">
|
||||
<Switch>
|
||||
<Route path="/login/verify/:token">
|
||||
<Login />
|
||||
</Route>
|
||||
<Route path="/login/reset/:token">
|
||||
<LoadSuspense>
|
||||
<Login />
|
||||
</Route>
|
||||
<Route path="/login/reset/:token">
|
||||
<Login />
|
||||
</Route>
|
||||
<Route path="/delete/:token">
|
||||
</LoadSuspense>
|
||||
</Route>
|
||||
<Route path="/delete/:token">
|
||||
<LoadSuspense>
|
||||
<ConfirmDelete />
|
||||
</Route>
|
||||
<Route path="/invite/:code">
|
||||
<CheckAuth blockRender>
|
||||
<Invite />
|
||||
</CheckAuth>
|
||||
<CheckAuth auth blockRender>
|
||||
<Invite />
|
||||
</CheckAuth>
|
||||
</Route>
|
||||
<Route path="/login">
|
||||
<CheckAuth>
|
||||
<Login />
|
||||
</CheckAuth>
|
||||
</Route>
|
||||
<Route path="/">
|
||||
<CheckAuth auth>
|
||||
</LoadSuspense>
|
||||
</Route>
|
||||
<Route path="/invite/:code">
|
||||
<CheckAuth blockRender>
|
||||
<Invite />
|
||||
</CheckAuth>
|
||||
<CheckAuth auth blockRender>
|
||||
<Invite />
|
||||
</CheckAuth>
|
||||
</Route>
|
||||
<Route path="/login">
|
||||
<CheckAuth>
|
||||
<Login />
|
||||
</CheckAuth>
|
||||
</Route>
|
||||
<Route path="/">
|
||||
<CheckAuth auth>
|
||||
<LoadSuspense>
|
||||
<RevoltApp />
|
||||
</CheckAuth>
|
||||
</Route>
|
||||
</Switch>
|
||||
</Suspense>
|
||||
</LoadSuspense>
|
||||
</CheckAuth>
|
||||
</Route>
|
||||
</Switch>
|
||||
</Context>
|
||||
</ErrorBoundary>
|
||||
);
|
||||
|
|
Loading…
Reference in a new issue