revite/src/context/revoltjs/RevoltClient.tsx

100 lines
2.9 KiB
TypeScript
Raw Normal View History

2021-08-05 09:47:00 -04:00
/* eslint-disable react-hooks/rules-of-hooks */
2021-12-11 16:04:12 -05:00
import { observer } from "mobx-react-lite";
2021-06-18 14:25:33 -04:00
import { Client } from "revolt.js";
2021-07-05 06:23:23 -04:00
import { createContext } from "preact";
import { useContext, useEffect, useMemo, useState } from "preact/hooks";
2021-07-05 06:23:23 -04:00
2021-12-11 16:04:12 -05:00
import { useApplicationState } from "../../mobx/State";
2021-07-05 06:23:23 -04:00
import Preloader from "../../components/ui/Preloader";
import { Children } from "../../types/Preact";
import { useIntermediate } from "../intermediate/Intermediate";
2021-12-11 16:04:12 -05:00
import { registerEvents } from "./events";
2021-07-05 06:23:23 -04:00
import { takeError } from "./util";
export enum ClientStatus {
2021-07-05 06:25:20 -04:00
READY,
2021-12-11 16:04:12 -05:00
LOADING,
2021-07-05 06:25:20 -04:00
OFFLINE,
DISCONNECTED,
CONNECTING,
RECONNECTING,
ONLINE,
}
2021-06-18 15:07:26 -04:00
export interface ClientOperations {
2021-07-05 06:25:20 -04:00
logout: (shouldRequest?: boolean) => Promise<void>;
2021-06-18 15:07:26 -04:00
}
export const AppContext = createContext<Client>(null!);
export const StatusContext = createContext<ClientStatus>(null!);
2021-12-11 16:04:12 -05:00
export const LogOutContext = createContext(() => {});
2021-06-18 15:07:26 -04:00
type Props = {
2021-07-05 06:25:20 -04:00
children: Children;
2021-06-18 15:07:26 -04:00
};
2021-12-11 16:04:12 -05:00
export default observer(({ children }: Props) => {
const state = useApplicationState();
2021-07-05 06:25:20 -04:00
const { openScreen } = useIntermediate();
2021-12-11 16:04:12 -05:00
const [client, setClient] = useState<Client>(null!);
const [status, setStatus] = useState(ClientStatus.LOADING);
const [loaded, setLoaded] = useState(false);
2021-07-05 06:25:20 -04:00
2021-12-11 16:04:12 -05:00
function logout() {
setLoaded(false);
client.logout(false);
}
2021-07-05 06:25:20 -04:00
2021-12-11 16:04:12 -05:00
useEffect(() => {
if (navigator.onLine) {
new Client().req("GET", "/").then(state.config.set);
}
2021-07-05 06:25:20 -04:00
}, []);
useEffect(() => {
2021-12-11 16:04:12 -05:00
if (state.auth.isLoggedIn()) {
setLoaded(false);
2021-12-11 16:04:12 -05:00
const client = state.config.createClient();
setClient(client);
client
.useExistingSession(state.auth.getSession()!)
.catch((err) => {
2021-07-05 06:25:20 -04:00
const error = takeError(err);
if (error === "Forbidden" || error === "Unauthorized") {
2021-12-11 16:04:12 -05:00
client.logout(true);
2021-07-05 06:25:20 -04:00
openScreen({ id: "signed_out" });
} else {
2021-12-11 16:04:12 -05:00
setStatus(ClientStatus.DISCONNECTED);
2021-07-05 06:25:20 -04:00
openScreen({ id: "error", error });
}
})
.finally(() => setLoaded(true));
2021-12-11 16:04:12 -05:00
} else {
setStatus(ClientStatus.READY);
setLoaded(true);
}
}, [state.auth.getSession()]);
useEffect(() => registerEvents(state.auth, setStatus, client), [client]);
2021-07-05 06:25:20 -04:00
2021-12-11 16:04:12 -05:00
if (!loaded || status === ClientStatus.LOADING) {
2021-07-05 06:25:20 -04:00
return <Preloader type="spinner" />;
}
return (
<AppContext.Provider value={client}>
<StatusContext.Provider value={status}>
2021-12-11 16:04:12 -05:00
<LogOutContext.Provider value={logout}>
2021-07-05 06:25:20 -04:00
{children}
2021-12-11 16:04:12 -05:00
</LogOutContext.Provider>
2021-07-05 06:25:20 -04:00
</StatusContext.Provider>
</AppContext.Provider>
);
2021-07-05 06:23:23 -04:00
});
export const useClient = () => useContext(AppContext);