forked from abner/for-legacy-web
Merge branch 'mobx'
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
import { Redirect } from "react-router-dom";
|
||||
|
||||
import { useContext } from "preact/hooks";
|
||||
import { useApplicationState } from "../../mobx/State";
|
||||
|
||||
import { Children } from "../../types/Preact";
|
||||
import { OperationsContext } from "./RevoltClient";
|
||||
import { useClient } from "./RevoltClient";
|
||||
|
||||
interface Props {
|
||||
auth?: boolean;
|
||||
@@ -11,11 +11,13 @@ interface Props {
|
||||
}
|
||||
|
||||
export const CheckAuth = (props: Props) => {
|
||||
const operations = useContext(OperationsContext);
|
||||
const auth = useApplicationState().auth;
|
||||
const client = useClient();
|
||||
const ready = auth.isLoggedIn() && typeof client?.user !== "undefined";
|
||||
|
||||
if (props.auth && !operations.ready()) {
|
||||
if (props.auth && !ready) {
|
||||
return <Redirect to="/login" />;
|
||||
} else if (!props.auth && operations.ready()) {
|
||||
} else if (!props.auth && ready) {
|
||||
return <Redirect to="/" />;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,22 +8,10 @@ import { useCallback, useContext, useEffect } from "preact/hooks";
|
||||
|
||||
import { useTranslation } from "../../lib/i18n";
|
||||
|
||||
import { connectState } from "../../redux/connector";
|
||||
import {
|
||||
getNotificationState,
|
||||
Notifications,
|
||||
shouldNotify,
|
||||
} from "../../redux/reducers/notifications";
|
||||
import { NotificationOptions } from "../../redux/reducers/settings";
|
||||
import { useApplicationState } from "../../mobx/State";
|
||||
|
||||
import { SoundContext } from "../Settings";
|
||||
import { AppContext } from "./RevoltClient";
|
||||
|
||||
interface Props {
|
||||
options?: NotificationOptions;
|
||||
notifs: Notifications;
|
||||
}
|
||||
|
||||
const notifications: { [key: string]: Notification } = {};
|
||||
|
||||
async function createNotification(
|
||||
@@ -38,9 +26,11 @@ async function createNotification(
|
||||
}
|
||||
}
|
||||
|
||||
function Notifier({ options, notifs }: Props) {
|
||||
function Notifier() {
|
||||
const translate = useTranslation();
|
||||
const showNotification = options?.desktopEnabled ?? false;
|
||||
const state = useApplicationState();
|
||||
const notifs = state.notifications;
|
||||
const showNotification = state.settings.get("notifications:desktop");
|
||||
|
||||
const client = useContext(AppContext);
|
||||
const { guild: guild_id, channel: channel_id } = useParams<{
|
||||
@@ -48,19 +38,13 @@ function Notifier({ options, notifs }: Props) {
|
||||
channel: string;
|
||||
}>();
|
||||
const history = useHistory();
|
||||
const playSound = useContext(SoundContext);
|
||||
|
||||
const message = useCallback(
|
||||
async (msg: Message) => {
|
||||
if (msg.author_id === client.user!._id) return;
|
||||
if (msg.channel_id === channel_id && document.hasFocus()) return;
|
||||
if (client.user!.status?.presence === Presence.Busy) return;
|
||||
if (msg.author?.relationship === RelationshipStatus.Blocked) return;
|
||||
if (!notifs.shouldNotify(msg)) return;
|
||||
|
||||
const notifState = getNotificationState(notifs, msg.channel!);
|
||||
if (!shouldNotify(notifState, msg, client.user!._id)) return;
|
||||
|
||||
playSound("message");
|
||||
state.settings.sounds.playSound("message");
|
||||
if (!showNotification) return;
|
||||
|
||||
const effectiveName = msg.masquerade?.name ?? msg.author?.username;
|
||||
@@ -220,7 +204,7 @@ function Notifier({ options, notifs }: Props) {
|
||||
channel_id,
|
||||
client,
|
||||
notifs,
|
||||
playSound,
|
||||
state,
|
||||
],
|
||||
);
|
||||
|
||||
@@ -268,7 +252,7 @@ function Notifier({ options, notifs }: Props) {
|
||||
};
|
||||
}, [
|
||||
client,
|
||||
playSound,
|
||||
state,
|
||||
guild_id,
|
||||
channel_id,
|
||||
showNotification,
|
||||
@@ -296,28 +280,17 @@ function Notifier({ options, notifs }: Props) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const NotifierComponent = connectState(
|
||||
Notifier,
|
||||
(state) => {
|
||||
return {
|
||||
options: state.settings.notification,
|
||||
notifs: state.notifications,
|
||||
};
|
||||
},
|
||||
true,
|
||||
);
|
||||
|
||||
export default function NotificationsComponent() {
|
||||
return (
|
||||
<Switch>
|
||||
<Route path="/server/:server/channel/:channel">
|
||||
<NotifierComponent />
|
||||
<Notifier />
|
||||
</Route>
|
||||
<Route path="/channel/:channel">
|
||||
<NotifierComponent />
|
||||
<Notifier />
|
||||
</Route>
|
||||
<Route path="/">
|
||||
<NotifierComponent />
|
||||
<Notifier />
|
||||
</Route>
|
||||
</Switch>
|
||||
);
|
||||
|
||||
@@ -1,26 +1,22 @@
|
||||
/* eslint-disable react-hooks/rules-of-hooks */
|
||||
import { Session } from "revolt-api/types/Auth";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { Client } from "revolt.js";
|
||||
import { Route } from "revolt.js/dist/api/routes";
|
||||
|
||||
import { createContext } from "preact";
|
||||
import { useContext, useEffect, useMemo, useState } from "preact/hooks";
|
||||
|
||||
import { dispatch } from "../../redux";
|
||||
import { connectState } from "../../redux/connector";
|
||||
import { AuthState } from "../../redux/reducers/auth";
|
||||
import { useApplicationState } from "../../mobx/State";
|
||||
|
||||
import Preloader from "../../components/ui/Preloader";
|
||||
|
||||
import { Children } from "../../types/Preact";
|
||||
import { useIntermediate } from "../intermediate/Intermediate";
|
||||
import { registerEvents, setReconnectDisallowed } from "./events";
|
||||
import { registerEvents } from "./events";
|
||||
import { takeError } from "./util";
|
||||
|
||||
export enum ClientStatus {
|
||||
INIT,
|
||||
LOADING,
|
||||
READY,
|
||||
LOADING,
|
||||
OFFLINE,
|
||||
DISCONNECTED,
|
||||
CONNECTING,
|
||||
@@ -29,179 +25,75 @@ export enum ClientStatus {
|
||||
}
|
||||
|
||||
export interface ClientOperations {
|
||||
login: (
|
||||
data: Route<"POST", "/auth/session/login">["data"],
|
||||
) => Promise<void>;
|
||||
logout: (shouldRequest?: boolean) => Promise<void>;
|
||||
loggedIn: () => boolean;
|
||||
ready: () => boolean;
|
||||
}
|
||||
|
||||
// By the time they are used, they should all be initialized.
|
||||
// Currently the app does not render until a client is built and the other two are always initialized on first render.
|
||||
// - insert's words
|
||||
export const AppContext = createContext<Client>(null!);
|
||||
export const StatusContext = createContext<ClientStatus>(null!);
|
||||
export const OperationsContext = createContext<ClientOperations>(null!);
|
||||
export const LogOutContext = createContext(() => {});
|
||||
|
||||
type Props = {
|
||||
auth: AuthState;
|
||||
children: Children;
|
||||
};
|
||||
|
||||
function Context({ auth, children }: Props) {
|
||||
export default observer(({ children }: Props) => {
|
||||
const state = useApplicationState();
|
||||
const { openScreen } = useIntermediate();
|
||||
const [status, setStatus] = useState(ClientStatus.INIT);
|
||||
const [client, setClient] = useState<Client>(
|
||||
undefined as unknown as Client,
|
||||
);
|
||||
const [client, setClient] = useState<Client>(null!);
|
||||
const [status, setStatus] = useState(ClientStatus.LOADING);
|
||||
const [loaded, setLoaded] = useState(false);
|
||||
|
||||
function logout() {
|
||||
setLoaded(false);
|
||||
client.logout(false);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
const client = new Client({
|
||||
autoReconnect: false,
|
||||
apiURL: import.meta.env.VITE_API_URL,
|
||||
debug: import.meta.env.DEV,
|
||||
});
|
||||
|
||||
setClient(client);
|
||||
setStatus(ClientStatus.LOADING);
|
||||
})();
|
||||
if (navigator.onLine) {
|
||||
new Client().req("GET", "/").then(state.config.set);
|
||||
}
|
||||
}, []);
|
||||
|
||||
if (status === ClientStatus.INIT) return null;
|
||||
|
||||
const operations: ClientOperations = useMemo(() => {
|
||||
return {
|
||||
login: async (data) => {
|
||||
setReconnectDisallowed(true);
|
||||
|
||||
try {
|
||||
const onboarding = await client.login(data);
|
||||
setReconnectDisallowed(false);
|
||||
const login = () =>
|
||||
dispatch({
|
||||
type: "LOGIN",
|
||||
session: client.session as Session,
|
||||
});
|
||||
|
||||
if (onboarding) {
|
||||
openScreen({
|
||||
id: "onboarding",
|
||||
callback: async (username: string) =>
|
||||
onboarding(username, true).then(login),
|
||||
});
|
||||
} else {
|
||||
login();
|
||||
}
|
||||
} catch (err) {
|
||||
setReconnectDisallowed(false);
|
||||
throw err;
|
||||
}
|
||||
},
|
||||
logout: async (shouldRequest) => {
|
||||
dispatch({ type: "LOGOUT" });
|
||||
|
||||
client.reset();
|
||||
dispatch({ type: "RESET" });
|
||||
|
||||
openScreen({ id: "none" });
|
||||
setStatus(ClientStatus.READY);
|
||||
|
||||
client.websocket.disconnect();
|
||||
|
||||
if (shouldRequest) {
|
||||
try {
|
||||
await client.logout();
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
},
|
||||
loggedIn: () => typeof auth.active !== "undefined",
|
||||
ready: () =>
|
||||
operations.loggedIn() && typeof client.user !== "undefined",
|
||||
};
|
||||
}, [client, auth.active, openScreen]);
|
||||
|
||||
useEffect(
|
||||
() => registerEvents({ operations }, setStatus, client),
|
||||
[client, operations],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
if (auth.active) {
|
||||
dispatch({ type: "QUEUE_FAIL_ALL" });
|
||||
if (state.auth.isLoggedIn()) {
|
||||
setLoaded(false);
|
||||
const client = state.config.createClient();
|
||||
setClient(client);
|
||||
|
||||
const active = auth.accounts[auth.active];
|
||||
client.user = client.users.get(active.session.user_id);
|
||||
if (!navigator.onLine) {
|
||||
return setStatus(ClientStatus.OFFLINE);
|
||||
}
|
||||
|
||||
if (operations.ready()) setStatus(ClientStatus.CONNECTING);
|
||||
|
||||
if (navigator.onLine) {
|
||||
await client
|
||||
.fetchConfiguration()
|
||||
.catch(() =>
|
||||
console.error("Failed to connect to API server."),
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
await client.fetchConfiguration();
|
||||
const callback = await client.useExistingSession(
|
||||
active.session,
|
||||
);
|
||||
|
||||
if (callback) {
|
||||
openScreen({ id: "onboarding", callback });
|
||||
}
|
||||
} catch (err) {
|
||||
setStatus(ClientStatus.DISCONNECTED);
|
||||
client
|
||||
.useExistingSession(state.auth.getSession()!)
|
||||
.catch((err) => {
|
||||
const error = takeError(err);
|
||||
if (error === "Forbidden" || error === "Unauthorized") {
|
||||
operations.logout(true);
|
||||
client.logout(true);
|
||||
openScreen({ id: "signed_out" });
|
||||
} else {
|
||||
setStatus(ClientStatus.DISCONNECTED);
|
||||
openScreen({ id: "error", error });
|
||||
}
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
await client.fetchConfiguration();
|
||||
} catch (err) {
|
||||
console.error("Failed to connect to API server.");
|
||||
}
|
||||
})
|
||||
.finally(() => setLoaded(true));
|
||||
} else {
|
||||
setStatus(ClientStatus.READY);
|
||||
setLoaded(true);
|
||||
}
|
||||
}, [state.auth.getSession()]);
|
||||
|
||||
setStatus(ClientStatus.READY);
|
||||
}
|
||||
})();
|
||||
// eslint-disable-next-line
|
||||
}, []);
|
||||
useEffect(() => registerEvents(state.auth, setStatus, client), [client]);
|
||||
|
||||
if (status === ClientStatus.LOADING) {
|
||||
if (!loaded || status === ClientStatus.LOADING) {
|
||||
return <Preloader type="spinner" />;
|
||||
}
|
||||
|
||||
return (
|
||||
<AppContext.Provider value={client}>
|
||||
<StatusContext.Provider value={status}>
|
||||
<OperationsContext.Provider value={operations}>
|
||||
<LogOutContext.Provider value={logout}>
|
||||
{children}
|
||||
</OperationsContext.Provider>
|
||||
</LogOutContext.Provider>
|
||||
</StatusContext.Provider>
|
||||
</AppContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
export default connectState<{ children: Children }>(Context, (state) => {
|
||||
return {
|
||||
auth: state.auth,
|
||||
sync: state.sync,
|
||||
};
|
||||
});
|
||||
|
||||
export const useClient = () => useContext(AppContext);
|
||||
|
||||
@@ -5,45 +5,35 @@ import { Message } from "revolt.js/dist/maps/Messages";
|
||||
|
||||
import { useContext, useEffect } from "preact/hooks";
|
||||
|
||||
import { dispatch } from "../../redux";
|
||||
import { connectState } from "../../redux/connector";
|
||||
import { QueuedMessage } from "../../redux/reducers/queue";
|
||||
import { useApplicationState } from "../../mobx/State";
|
||||
|
||||
import { setGlobalEmojiPack } from "../../components/common/Emoji";
|
||||
|
||||
import { AppContext } from "./RevoltClient";
|
||||
|
||||
type Props = {
|
||||
messages: QueuedMessage[];
|
||||
};
|
||||
|
||||
function StateMonitor(props: Props) {
|
||||
export default function StateMonitor() {
|
||||
const client = useContext(AppContext);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch({
|
||||
type: "QUEUE_DROP_ALL",
|
||||
});
|
||||
}, []);
|
||||
const state = useApplicationState();
|
||||
|
||||
useEffect(() => {
|
||||
function add(msg: Message) {
|
||||
if (!msg.nonce) return;
|
||||
if (!props.messages.find((x) => x.id === msg.nonce)) return;
|
||||
|
||||
dispatch({
|
||||
type: "QUEUE_REMOVE",
|
||||
nonce: msg.nonce,
|
||||
});
|
||||
if (
|
||||
!state.queue.get(msg.channel_id).find((x) => x.id === msg.nonce)
|
||||
)
|
||||
return;
|
||||
state.queue.remove(msg.nonce);
|
||||
}
|
||||
|
||||
client.addListener("message", add);
|
||||
return () => client.removeListener("message", add);
|
||||
}, [client, props.messages]);
|
||||
}, [client]);
|
||||
|
||||
// Set global emoji pack.
|
||||
useEffect(() => {
|
||||
const v = state.settings.get("appearance:emoji");
|
||||
v && setGlobalEmojiPack(v);
|
||||
}, [state.settings.get("appearance:emoji")]);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export default connectState(StateMonitor, (state) => {
|
||||
return {
|
||||
messages: [...state.queue],
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,153 +1,37 @@
|
||||
/**
|
||||
* This file monitors changes to settings and syncs them to the server.
|
||||
*/
|
||||
import isEqual from "lodash.isequal";
|
||||
import { UserSettings } from "revolt-api/types/Sync";
|
||||
import { ClientboundNotification } from "revolt.js/dist/websocket/notifications";
|
||||
|
||||
import { useCallback, useContext, useEffect, useMemo } from "preact/hooks";
|
||||
import { useEffect } from "preact/hooks";
|
||||
|
||||
import { dispatch } from "../../redux";
|
||||
import { connectState } from "../../redux/connector";
|
||||
import { Notifications } from "../../redux/reducers/notifications";
|
||||
import { Settings } from "../../redux/reducers/settings";
|
||||
import {
|
||||
DEFAULT_ENABLED_SYNC,
|
||||
SyncData,
|
||||
SyncKeys,
|
||||
SyncOptions,
|
||||
} from "../../redux/reducers/sync";
|
||||
import { useApplicationState } from "../../mobx/State";
|
||||
|
||||
import { Language } from "../Locale";
|
||||
import { AppContext, ClientStatus, StatusContext } from "./RevoltClient";
|
||||
import { useClient } from "./RevoltClient";
|
||||
|
||||
type Props = {
|
||||
settings: Settings;
|
||||
locale: Language;
|
||||
sync: SyncOptions;
|
||||
notifications: Notifications;
|
||||
};
|
||||
|
||||
const lastValues: { [key in SyncKeys]?: unknown } = {};
|
||||
|
||||
export function mapSync(
|
||||
packet: UserSettings,
|
||||
revision?: Record<string, number>,
|
||||
) {
|
||||
const update: { [key in SyncKeys]?: [number, SyncData[key]] } = {};
|
||||
for (const key of Object.keys(packet)) {
|
||||
const [timestamp, obj] = packet[key];
|
||||
if (timestamp < (revision ?? {})[key] ?? 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let object;
|
||||
if (obj[0] === "{") {
|
||||
object = JSON.parse(obj);
|
||||
} else {
|
||||
object = obj;
|
||||
}
|
||||
|
||||
lastValues[key as SyncKeys] = object;
|
||||
update[key as SyncKeys] = [timestamp, object];
|
||||
}
|
||||
|
||||
return update;
|
||||
}
|
||||
|
||||
function SyncManager(props: Props) {
|
||||
const client = useContext(AppContext);
|
||||
const status = useContext(StatusContext);
|
||||
export default function SyncManager() {
|
||||
const client = useClient();
|
||||
const state = useApplicationState();
|
||||
|
||||
// Sync settings from Revolt.
|
||||
useEffect(() => {
|
||||
if (status === ClientStatus.ONLINE) {
|
||||
client
|
||||
.syncFetchSettings(
|
||||
DEFAULT_ENABLED_SYNC.filter(
|
||||
(x) => !props.sync?.disabled?.includes(x),
|
||||
),
|
||||
)
|
||||
.then((data) => {
|
||||
dispatch({
|
||||
type: "SYNC_UPDATE",
|
||||
update: mapSync(data),
|
||||
});
|
||||
});
|
||||
state.sync.pull(client);
|
||||
}, [client]);
|
||||
|
||||
client
|
||||
.syncFetchUnreads()
|
||||
.then((unreads) => dispatch({ type: "UNREADS_SET", unreads }));
|
||||
}
|
||||
}, [client, props.sync?.disabled, status]);
|
||||
|
||||
const syncChange = useCallback(
|
||||
(key: SyncKeys, data: unknown) => {
|
||||
const timestamp = +new Date();
|
||||
dispatch({
|
||||
type: "SYNC_SET_REVISION",
|
||||
key,
|
||||
timestamp,
|
||||
});
|
||||
|
||||
client.syncSetSettings(
|
||||
{
|
||||
[key]: data as string,
|
||||
},
|
||||
timestamp,
|
||||
);
|
||||
},
|
||||
[client],
|
||||
);
|
||||
|
||||
const disabled = useMemo(
|
||||
() => props.sync.disabled ?? [],
|
||||
[props.sync.disabled],
|
||||
);
|
||||
for (const [key, object] of [
|
||||
["appearance", props.settings.appearance],
|
||||
["theme", props.settings.theme],
|
||||
["locale", props.locale],
|
||||
["notifications", props.notifications],
|
||||
] as [SyncKeys, unknown][]) {
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
useEffect(() => {
|
||||
if (disabled.indexOf(key) === -1) {
|
||||
if (typeof lastValues[key] !== "undefined") {
|
||||
if (!isEqual(lastValues[key], object)) {
|
||||
syncChange(key, object);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lastValues[key] = object;
|
||||
}, [key, syncChange, disabled, object]);
|
||||
}
|
||||
// Keep data synced.
|
||||
useEffect(() => state.registerListeners(client), [client]);
|
||||
|
||||
// Take data updates from Revolt.
|
||||
useEffect(() => {
|
||||
function onPacket(packet: ClientboundNotification) {
|
||||
if (packet.type === "UserSettingsUpdate") {
|
||||
const update: { [key in SyncKeys]?: [number, SyncData[key]] } =
|
||||
mapSync(packet.update, props.sync.revision);
|
||||
|
||||
dispatch({
|
||||
type: "SYNC_UPDATE",
|
||||
update,
|
||||
});
|
||||
state.sync.apply(packet.update);
|
||||
}
|
||||
}
|
||||
|
||||
client.addListener("packet", onPacket);
|
||||
return () => client.removeListener("packet", onPacket);
|
||||
}, [client, disabled, props.sync]);
|
||||
}, [client]);
|
||||
|
||||
return null;
|
||||
return <></>;
|
||||
}
|
||||
|
||||
export default connectState(SyncManager, (state) => {
|
||||
return {
|
||||
settings: state.settings,
|
||||
locale: state.locale,
|
||||
sync: state.sync,
|
||||
notifications: state.notifications,
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
import { Client } from "revolt.js/dist";
|
||||
import { Message } from "revolt.js/dist/maps/Messages";
|
||||
import { ClientboundNotification } from "revolt.js/dist/websocket/notifications";
|
||||
|
||||
import { StateUpdater } from "preact/hooks";
|
||||
|
||||
import { dispatch } from "../../redux";
|
||||
import Auth from "../../mobx/stores/Auth";
|
||||
|
||||
import { ClientOperations, ClientStatus } from "./RevoltClient";
|
||||
import { ClientStatus } from "./RevoltClient";
|
||||
|
||||
export let preventReconnect = false;
|
||||
let preventUntil = 0;
|
||||
@@ -16,10 +14,12 @@ export function setReconnectDisallowed(allowed: boolean) {
|
||||
}
|
||||
|
||||
export function registerEvents(
|
||||
{ operations }: { operations: ClientOperations },
|
||||
auth: Auth,
|
||||
setStatus: StateUpdater<ClientStatus>,
|
||||
client: Client,
|
||||
) {
|
||||
if (!client) return;
|
||||
|
||||
function attemptReconnect() {
|
||||
if (preventReconnect) return;
|
||||
function reconnect() {
|
||||
@@ -36,40 +36,19 @@ export function registerEvents(
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
let listeners: Record<string, (...args: any[]) => void> = {
|
||||
connecting: () =>
|
||||
operations.ready() && setStatus(ClientStatus.CONNECTING),
|
||||
connecting: () => setStatus(ClientStatus.CONNECTING),
|
||||
|
||||
dropped: () => {
|
||||
if (operations.ready()) {
|
||||
setStatus(ClientStatus.DISCONNECTED);
|
||||
attemptReconnect();
|
||||
}
|
||||
},
|
||||
|
||||
packet: (packet: ClientboundNotification) => {
|
||||
switch (packet.type) {
|
||||
case "ChannelAck": {
|
||||
dispatch({
|
||||
type: "UNREADS_MARK_READ",
|
||||
channel: packet.id,
|
||||
message: packet.message_id,
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
message: (message: Message) => {
|
||||
if (message.mention_ids?.includes(client.user!._id)) {
|
||||
dispatch({
|
||||
type: "UNREADS_MENTION",
|
||||
channel: message.channel_id,
|
||||
message: message._id,
|
||||
});
|
||||
}
|
||||
setStatus(ClientStatus.DISCONNECTED);
|
||||
attemptReconnect();
|
||||
},
|
||||
|
||||
ready: () => setStatus(ClientStatus.ONLINE),
|
||||
|
||||
logout: () => {
|
||||
auth.logout();
|
||||
setStatus(ClientStatus.READY);
|
||||
},
|
||||
};
|
||||
|
||||
if (import.meta.env.DEV) {
|
||||
@@ -89,19 +68,15 @@ export function registerEvents(
|
||||
}
|
||||
|
||||
const online = () => {
|
||||
if (operations.ready()) {
|
||||
setStatus(ClientStatus.RECONNECTING);
|
||||
setReconnectDisallowed(false);
|
||||
attemptReconnect();
|
||||
}
|
||||
setStatus(ClientStatus.RECONNECTING);
|
||||
setReconnectDisallowed(false);
|
||||
attemptReconnect();
|
||||
};
|
||||
|
||||
const offline = () => {
|
||||
if (operations.ready()) {
|
||||
setReconnectDisallowed(true);
|
||||
client.websocket.disconnect();
|
||||
setStatus(ClientStatus.OFFLINE);
|
||||
}
|
||||
setReconnectDisallowed(true);
|
||||
client.websocket.disconnect();
|
||||
setStatus(ClientStatus.OFFLINE);
|
||||
};
|
||||
|
||||
window.addEventListener("online", online);
|
||||
|
||||
Reference in New Issue
Block a user